If i have code like:
self.view.addSubview(SomeImage1)
self.view.addSubview(SomeImage2)
self.view.addSubview(SomeImage3)
How do I switch places of view, i understand that the first one would be at index 0 and second at index 1, so is there a way to manually set view index, i am new at managing view and havent found any tutorial good enough to solve my problems.
There's a full set of UIView methods that copes with that:
func bringSubviewToFront(_ view: UIView)
func sendSubviewToBack(_ view: UIView)
func removeFromSuperview()
func insertSubview(_ view: UIView, atIndex index: Int)
func insertSubview(_ view: UIView, aboveSubview siblingSubview: UIView)
func insertSubview(_ view: UIView, belowSubview siblingSubview: UIView)
func exchangeSubviewAtIndex(_ index1: Int, withSubviewAtIndex index2: Int)
...and so on.
You shouldn't be using array indexes to move views.
Related
I have a MKMapView in one of my static cells. Instead of being able move the map around, I would like the user to be able to tap the map and have it expand full screen. Then within the full screen the user can move around and zoom in and out. They will eventually be able to see where I have pins placed based on other users' city where they are located.
I am getting an error when the map is tapped.
Thread 1: "-[HomeTableViewController triggerTouchAction:]: unrecognized selector sent to instance 0x115e2f8a0"
Here is the important code for the map and touch gesture for the controller:
import UIKit
import CoreLocation
import MapKit
class HomeTableViewController: UITableViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
let gestureRecognizer = UITapGestureRecognizer(target: self, action:"triggerTouchAction:")
mapView.addGestureRecognizer(gestureRecognizer)
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 7
}
func triggerTouchAction(gestureReconizer: UITapGestureRecognizer) {
//Add alert to show it works
print("Map Tapped")
}
}
I would love to be able to move forward with this part of my app. Thank you in advance for helping me out. I am very new to coding and wish I had gotten my degree in it.
My NSCollectionView crashes when calling makeItem(withIdentifier identifier: String, for indexPath: IndexPath). numberOfItemsInSection returns the correct value. If I call makeItem... in viewDidLoad rather than in itemForRepresentedObject I see an error indicating that the indexPath is out of bounds. How can this be?
The collection view loads like this:
class TagCollectionViewController: NSViewController, NSCollectionViewDataSource {
fileprivate static let itemIdentifier = "TagItem"
#IBOutlet var collectionView: NSCollectionView!
fileprivate var tags = List<Tag>.init()
override func viewDidLoad() {
super.viewDidLoad()
let nib = NSNib(nibNamed: "TagCollectionViewItem", bundle: nil)
collectionView.register(nib, forItemWithIdentifier: TagCollectionViewController.itemIdentifier)
collectionView.dataSource = self
}
(The List collection is a Realm class)
During viewWillAppear() the tags collection is populated from a ReSwift state:
override func viewWillAppear() {
for image in mainStore.state.selectedImages {
for tag in image.tags {
tags.append(tag)
}
}
super.viewWillAppear()
}
Solved it.
When I created the .xib for the item I added an NSCollectionViewItem object but didn't wire up the view to my custom view.
To recap, for anyone who gets caught out by this, the steps to creating a NSCollectionViewItem are:
Create the nib and configure your views
Add an NSCollectionViewItem object to your nib
Wire up your view (and any other views) to the object
Register the nib with the collectionView in your view controller
I'm still very new to programming in Swift, (and never with Objective C). What I'm trying to do is add to the NSTableView when I've clicked on an item in the current tableview. The items seem to be adding when clicked, but the table does not seem to be refreshing with the new things in the array.
I've tried various things over the last few days, getting it to run reloadData on main thread and UI thread, etc but I'm feel like I'm just hitting the wall (it surely can't be this hard to do something so simple like I can in a couple minutes in Java)....
Have I missed something very obvious? (Code below)
class TableViewController: NSTableView, NSTableViewDataSource, NSTableViewDelegate {
var items: [String] = ["Eggs", "Milk"]
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result : TableCell = tableView.makeViewWithIdentifier(tableColumn!.identifier, owner: self) as! TableCell
result.itemField.stringValue = items[row]
return result
}
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
return items.count
}
func tableViewSelectionDidChange(notification: NSNotification) {
let index = notification.object!.selectedRow
if (index != -1) {
NSLog("#%d", index)
items.append("Blah")
NSLog("#%d", items.count)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.reloadData()
})
}
}
func relloadData() { //relload is not a typo
self.reloadData()
}
}
If you're binding your user interface to the items property of your view controller subclass, you need to mark it as it a Dynamic Variable:
dynamic var items: [String] = ["Eggs", "Milk"]
Place the dynamic keyword before the property declaration and I think it will solve your problem.
Note that Ken's comment also makes a good point in that this code probably should be written as an NSViewController subclass, instead of a subclass of NSTableView.
If you're using Storyboards, the custom view controller subclass would be a View Controller object for the view containing your table view. If you're using a xib file for the view, the view controller subclass would be the File's Owner. In either case, you would connect the table view's delegate and data source outlets to that object.
I am trying to link to another view controller by pressing a button which i have named 'find'. The issue is with the pickerView. i want the 'service' selected from the pickerView to determine which page you end up on. For example, you select 'bars' in the pickerView, you click the 'find' button and it takes you to the bars view controller page.
Here is my code which controls the picker and the find button.
import UIKit
class ViewController: UIViewController, UIPickerViewDelegate {
#IBOutlet weak var SelectedService: UILabel!
#IBAction func Find(sender: AnyObject) {
}
#IBOutlet weak var ItemLabel: UILabel!
var services = ["Cafe","Coffee Shops","Bar","Takeaway","Sunday Roast","Shoe Mender","Craft Shops","Electrical"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return services.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String!{
return services[row]
}
}
I am new to coding with swift so please could you explain your answer in a simple way.
Thank you very much
Shaun
In #IBAction func Find() you could have switch statement where you check which item from UIPickerView was selected, and based on that you can present desired view controller like this:
let cafeViewController: CafeViewController = CafeViewController()
self.presentViewController(cafeViewController, animated: true, completion: nil)
But are you sure you need it's own view controller for every item? They'll probably look exactly the same, only presented data will be different... so you could use just one view controller, send picked item in func prepareForSegue() and according on that prepare data in viewDidLoad() in that view controller.
Or at least try to reuse as much as you can creating some base class for your view controller and then create subclass for each service.
I have tableview and I created the custom xib uiview as "detailview" for it. I want to show this detailview at the center of scrolled area when tapped to tableview cell. I can show this view but cannot centralized it. when I set value to frame manually, subview will be at center (approximately) but when I tap the cell which is at the bottom, the subview is appearing at the top of page and also it is moving when i scroll the tableview.
Please help me to show this view at the center of the scrolled area and be fixed
Here is my codes;
Detail View :
class TopTenDetailView: UIView {
var screenWidth:CGFloat = UIScreen.mainScreen().bounds.width*0.08
var screenHeight :CGFloat = UIScreen.mainScreen().bounds.height*0.08
class func instanceFromNib() -> UIView {
return UINib(nibName: "TopTenDetail", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
}
override func awakeFromNib() {
super.awakeFromNib()
self.layer.cornerRadius=10
let testFrame : CGRect = CGRectMake(screenWidth,screenHeight,320,480)
self.frame = testFrame
self.userInteractionEnabled=true
}
#IBAction func close(sender: UIButton) {
self.hidden=true
}
}
And TableViewController's method ;
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var detailView = TopTenDetailView.instanceFromNib
self.view.addSubview(detailView())
}
The way this is setup has many problems and i would be surprised if it actually ever works as intended.
A much better, simpler setup uses a OverFullScreen presentation style and it goes like this:
Create a separate UIViewController for your detail view, let's call it DetailViewController use Interface Builder. Make sure to set the background color to CLEAR
Wire up a segue from the "base" UIViewController that holds your UITableView to DetailViewController and give the segue a name. Let's call it 'detailSegue' , basically drag from one view controller to the other. Make sure that you are not dragging from the view but from the yellow icon at the top of the view controller. You are done in Interface Builder.
Ok, now for the code:
// MARK : - UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("detailSegue", sender: self)
}
// MARK: - segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let vc = segue.destinationViewController as? UIViewController{
vc.modalPresentationStyle = .OverFullScreen
}
}
The OverFullScreen presentation style uses a proper UIViewController modal segue but leaves the presenting UIViewController visible under the presented one.
You can then just layout whatever you want on DetailViewController using Interface Builder and autolayout without having to do hacky match calculations on the layout at runtime.
Hope it helps!