I have a navigation controller as the initial view. It goes to VC1 which has 3 buttons, and each button is tied to an action that sets a parameter in VC2 before invoking performSegueWithIdentifier("goNow", sender: nil). I have this in my VC1 too.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "goNow") {
if let sView: SViewController = segue.destinationViewController as? SViewController {
sView.action = self.action
}
}
}
When invoked, VC2 appears for a few seconds and it terminates with EXC_BAD_ACCESS.
I am not extremely familiar with Swift, but I know that there are some questions when attempting to compare strings. Instead of using:if (segue.identifier == "goNow")
~ edit ~
Setting the class in Interface Builder (storyboard) for the destination view controller.
Create a String Variable using the segue.identifier value and compare the two like this:
let segueID = String(segue.identifier)
let segueToOpen = "goNow"
let isEqual = (segueID == segueToOpen)
// Now your if statement
if isEqual {
// ...
}
Also, you might want to consider separating the logic in the next if statement to read something like:
let sView: SViewController = segue.destinationViewController
Here is an excerpt from RayWenderlick's site and using the as operator:
Related
Through using a loop I've programmatically created a bunch of UIButtons. Each of these triggers the same segue to another View Controller which is supposed to display some information related to the button.
For this to work, I need to send at least one attribute/variable linked to the specific button tapped through the segue.
One option I tried was creating a new UIButton class to hold the attribute.
class statButton: UIButton {
var buttonIndex = Int()
}
If this even works, how would I access that data here:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "StatDetailSegue" {
if let destinationVC = segue.destination as? StatDetailViewController {
destinationVC.statTitle = // need to access here
}
}
}
The variable I need to send is a value in a dictionary
You have to make sure that the sender is a statButton, and then cast its buttonIndex property to a proper String:
if let destinationVC = segue.destination as? StatDetailViewController,
let index = (sender as? statButton).buttonIndex {
destinationVC.statTitle = String(index) //this is supposing that destinationVC.statTitle expects a String
}
P.S: It is a convention in Swift to have the names of classes with an uppercase first letter:
class statButton: UIButton { ... }
I have included images to hopefully make this easier to understand. My FirstViewController has a collection view with a list of users from my firebase database.When I click on the users I am segued to a DetailedViewController that has more information about the user that was clicked. Within that viewController, the goal is to click on the compose button and segue to a viewController that allows me to chat with the user, whose profile I clicked on.
I have gotten as far as this for segueing from DetailedViewController to Message user 1.
#IBAction func SendMessage(_ sender: Any) {
performSegue(withIdentifier: "chat", sender: self)
}
I am not sure how to make sure I am sending the particular user I click on a message.
This is how I am passing data from FirstViewController to DetailedViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "details" {
if let indexPaths = self.CollectionView!.indexPathsForSelectedItems{
let vc = segue.destination as! BookDetailsViewController
let cell = sender as! UICollectionViewCell
let indexPath = self.CollectionView!.indexPath(for: cell)
let post = self.posts[(indexPath?.row)!] as! [String: AnyObject]
let Booked = post["title"] as? String
vc.Booked = Booked
print(indexPath?.row)
} }
One route to take is in your DetailViewController class, or whatever class you have implementing performSegue(withIdentifier:, sender:), add this:
override public func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "chat", let dest = segue.destination as? ChatViewController else {
return
}
dest.user = self.user
}
I don't know how you have the user declared but if user is an object, do what I have above. If you're saying user as a way to umbrella multiple properties you want to pass.. do this:
dest.name = self.name
dest.number = self.number
//etc
prepare(for segue:, sender:) allows you to intercept any segue from it's class and set up whatever variables needed before the performSegue(...) executes. To target your code to a specific segue/destination/situation, make sure your code runs a check on those constraints before executing; otherwise the code will execute on all segues implemented in the class. In my example, I used your segue's identifier as that check.
I want to scan a QR code (doing this example: http://humberaquino.me/qrcode-scanning-in-swift/), however I have a problem with this code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let barcodeViewController: BarcodeViewController = segue.destinationViewController as! BarcodeViewController
barcodeViewController.delegate = self
}
I got this:
When I change this to as!, I'm getting:
Thread 1: signal SIGABRT on this line.
If you have more than one segue on that view controller, it may be another one firing. checking segue.identifier is one way of making sure you're on the right one. If the behaviour is based on the class you can do this :
if let barcodeViewController = segue.destinationViewController as? BarcodeViewController
{
barcodeViewController.delegate = self
}
I've looked around many threads and haven't benefitted with my issue. My issue lies in my 3rd VC where the user taps an 'Edit UIBarButtonItem' which segues them to the 4th VC. The segue ID is correct and both VC's 3 and 4 are static table VC's, but 4 is embedded in a nav controller and 3 isn't. i want the data in the textfields in VC 3 to be 'copied' to the almost identical looking textfields in VC 4, so that changes can be made by the user and updated. When i type cast my destination segue as the 4th VC inside prepareForSegue, it returns nil and the instance of data inside doesn't get moved to the 4th VC since 'if let' is being used. Why does it return nil? I've looked up the life cycle of segues too but haven't learnt much, all other VC's are fine.
I have tried both below and both return nil for VC 4
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EditSegue" {
print("correct segue name")
if let editVC: EditTableViewController = segue.destinationViewController as? EditTableViewController {
editVC.instanceOfData = self.instanceOfData //instance of data in 4th VC = instanceOfData in 3rd VC
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let editVC = segue.destinationViewController as? EditTableViewController
if segue.identifier == "EditSegue" {
editVC.instanceOfData = self.instanceOfData
}
}
I could be doing something obviously wrong which i haven't come across yet! I've successfully transferred data between two VC's before but not when instances have been passed around between VC's.
Any help is appreciated, thanks.
This is a totally dumb question I am sure. I have a viewcontroller that is inside a navigation controller that is inside a TabBarController. Apple says this is the right way to implement that setup. However, how can I prepareForSeque to that complex and send data to the first ViewController.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "presentActionItems" {
println("preparing")
let tabBarController:actionItemsTabController = segue.destinationViewController as! actionItemsTabController
let navigationController = ???
let viewController = ???
viewController.givenURL = actionItemsURL
}
}
I am sure this is an easy question, can I have some help.
Try this in your TabController's viewDidLoad after passing it your data
let firstViewController : UIViewController = self.viewControllers.objectAtIndex(0).topViewController;
firstViewController.this = self.this;
firstViewController.that = self.that;