when user clicked button
let uvc: UINavigationController =
self.storyboard?.instantiateViewController(withIdentifier: "nationSelect") as! UINavigationController
uvc.modalTransitionStyle = UIModalTransitionStyle.coverVertical
self.present(uvc, animated: true, completion: nil)
run this code.
identifier:nationSelect storyboard img
cell, closebutton, VC segue unwind img
and
button vc have this function
#IBAction func unwindFromPostCodeSelectionView(_ sender: UIStoryboardSegue) {
print("unwindFromPostCodeSelectionView")
}
and nationSelect VC
when collectionview's cell clicked
run this code
performSegue(withIdentifier: unwind, sender: nil)
and prepare function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let identifier = segue.identifier, identifier == unwind else{
return
}
guard let vc = segue.destination as? CurationRequestViewController else {
return
}
vc.getAddress.setTitle( (continent.text ?? " ") + " " + nation , for: .normal)
}
but i got this error
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () has no segue with identifier 'unwind''
help me plz!!!
Looks like you are trying to implement unwind segue and you missed to specify the identifier for unwind segue.
Here are the steps to properly implement unwind segue:
Step 1: If you are trying to implement unwind segue from Vc2 to Vc1 (Coming back to VC1 from VC2) then in VC1 add the IBAction as
#IBAction func unwindToViewController1(segue : UIStoryboardSegue) {
//you will get control back here when you unwind
}
Step 2:
Open storyboard, select VC2 and control drag from ViewController to Exit option in storyboard as shown below
This should show a popover and the method you just declared select it.
Step 3: (Step I think you missed)
Select the unwind segue you just added and provide a identifier to it.
Step 4:
Now whenever you wanna return back to VC1 you can simply call
self.performSegue(withIdentifier: "unwindSegueToViewController1", sender: nil)
Hope it helps :) Happy coding
Related
I'm working on an app where I have an error page displayed incase there is a network problem. The app has several storyboards, and this can happen anywhere.
func displayErrorPage(errorCode: ErrorCode) -> Void {
if !isDisplayingError {
DispatchQueue.main.async {
self.isDisplayingError = true
let storyboard = UIStoryboard(name: "alert", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "AlertScreen") as! AlertVC
controller.errorCode = errorCode
UIApplication.shared.topViewController?.present(controller, animated: true, completion: nil)
}
}
}
I would like to use unwind to dismiss it, to clear out any views and get back to the home page. I have used this in the alert view to close, but sometimes doesn't work.
#IBAction func closeBtn(_ sender: Any) {
flowError = true
NetworkManager.shared().isDisplayingError = false
performSegue(withIdentifier: "unwindToSH", sender: self)
}
Anyone with some pointers?
Create the unwind segue IBAction in the view controller you want to unwind to.
Perhaps in your case it is HomeViewController. Add this code inside your HomeViewController
#IBAction func unwindToHomeVC(segue: UIStoryboardSegue) {}
Wire up the unwind segue - Control drag from AlertVC’s ViewController icon to exit icon in the storyboard choose the unwind segue action (unwindToHomeVC) that was created in step 1 from the list of IBActions.
Specify a segue Identifier - specify its identifier in the Attributes Inspector of the Utilities Pane. Ex: “unwindToHomeVC”
Trigger unwind segue programmatically - trigger that in the appropriate place. In your case close button action
self.performSegue(withIdentifier: "unwindToMenu", sender: self)
It will work even if you work with multiple storyboard as well, if your setup is right. I hope that this one would help you.
Thanks
I want to switch between viewController by using containerViewController.
For this I created multiple segues and viewController.
when I run
func segueIdentifierReceivedFromParent(_ identifier: String){
self.segueIdentifier = identifier
self.performSegue(withIdentifier: self.segueIdentifier, sender: nil)
}
in it's parent controller file it works fine but when I called it through other controller file it gives error
ContainerViewController: 0x7fd703707b40>) has no segue with identifier 'second''
This is how i called it in other viewController
let vc = ParentViewController()
vc.segueIdentifierReceivedFromParent("second")
Here "second" is the Identifier given to segue in storyBoard
Above code is written in AddTarget of button.
So when I tap button I get Error
If you are in same a storyBoard then you can simply do this -
Take a button in your firstVC and ctrl + drag a segue upto your secondVC. Then click on the segue. (the round thing on between two view controller). -
And set a identifier for that (here about is the identifier, you can give any name for this)-
Here is the code -
#IBAction func UserDetailVC(sender: AnyObject) {
self.performSegue(withIdentifier: "segueIdentifierName", sender: sender)
}
I am trying to pass some data from selected row via segue to another viewcontroller but I cannot. I tried almost everything, but I always get:
2016-06-16 18:41:20.069 Wine Dictionary[3282:55647] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<Wine_Dictionary.DetailUI: 0x7f8a1ae2fa60>) has no segue with identifier 'SegueToDetailUI''
I already tried changing method, changing identifier etc.
Here is the screenshot of the code: http://prntscr.com/bh6e6l
Here is the screenshot of the storyboard and segue identifier: http://prntscr.com/bh6f6q
delete your code in didSelectRowAtIndexPath and add this
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "SegueToDetailUI") {
let selectedInfo = self.NAME?[indexPath.row]
let indexPath = tableView.indexPathForSelectedRow
let destinationVC = segue.destinationViewController as! DetailUI
destinationVC.programVar = selectedInfo!
}
}
assuming I spelled everything correctly (if not just correct my spelling)
Try deleting your segue and recreate it..
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToDetailUI")
{
if let rowselect = tableView!.indexPathForSelectedRow
{
let selectedInfo =self.NAME?[rowselect]
let moveVC:DetailUI = segue.destinationViewController as! DetailUI
moveVC.programVar = selectedInfo!
}
}
}
Since your segue goes from MainUI to DetailUI, performSegueWithIdentifier("SegueToDetailUI") musts be run from MainUI, the view controller at the origin of the segue.
Invoking this method will instantiate the DetailUI view controller, and push it on the screen.
Configuration of the newly created DetailUI view controller happens in the method MainUI.prepareForSegue. That's where you'll provide the programVar property.
Remember: when you use storyboards, you never never never instantiate view controllers yourself (let vc = MyViewController()). Instead, you'll always use one of the NSStoryboard.instantiateViewController... methods, or NSViewController.performSegue(...).
I am using for the first time the Unwind Segue approach. I have multiple view controllers as can be seen in the picture below (a few of them shown of course). In the Edit Profile I have a Done button. Once clicked I trigger an IBAction that triggers an unwind segue.
Here is the code for the Done button in the nav bar:
#IBAction func unwindToMainViews(sender: UIStoryboardSegue) {
//let sourceViewController = sender.sourceViewController
self.performSegueWithIdentifier("unwindToMainSegue", sender: self)
}
and in the
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
I am doing the following to pass data from Edit Profile back to Home View
if (segue.identifier == "unwindToMainSegue") {
// pass data to next view
let tabCtrl = segue.destinationViewController as! UITabBarController
let destinationVC = tabCtrl.viewControllers![0] as! HomeViewController
destinationVC.userObject = self.userObject;
}
When segue identifier is matched and code is executed (to transfer userObject from this controller to another), it triggers the error:
Could not cast value of type 'app.EditProfileViewController' (0x100b99d80) to 'UITabBarController' (0x104a1d030).
How can this error be fixed? I am surprised since i am casting to UITabBarController so thought it should work.
You don't return to the UITabBarController in an unwind segue. You return to the ViewController that triggered the original segue, or one if its ancestors.
As #jlehr stated in the comments:
Unwind segues don't return to anything; they dismiss any pushed and
presented view controllers between the source and destination view
controller. The destination is wherever the implementation of the
unwind method is found, regardless of how the source view controller
was presented.
To unwind to the viewController that triggered the original segue, you need to implement the #IBAction func returnToHere(segue: UIStoryboardSegue) function in the viewController you want to return to.
Then when you set up your Done button by dragging to the Exit icon, you select returnToHere from the pop-up.
To pass data back to the sourceViewController, give your unwind segue an identifier such as "unwindToSource", then override prepareForSegue in the viewController you are returning from:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "unwindToSource" {
let dvc = segue.destinationViewController as! SourceViewController
dvc.userObject = self.userObject
}
}
I have a tableview with buttons each containing a tag (according to indexPath.row), and when I press a particular button the details of the contents of that cell (which relates to a class called EventEntity) is meant to be passed through a 'prepareForSegue' method to another screen.
The value is assigned in the 'infoButtonDidPress' method as shown below:
func infoButtonDidPress(sender: UIButton){
eventPressed = eventEntities[sender.tag]
println (eventPressed.name) // prints the name, all good here.
}
The problem is that when I assign the contents of eventPressed to the destinationVC in 'prepareForSegue', they are nil. Code below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "infoButtonSegue"){
var svc = segue.destinationViewController as! EventDetailsViewController;
println (eventPressed.name) // NOPE.
svc.name = eventPressed.name //also NOPE!
}
eventPressed is declared above viewDidLoad:
var eventPressed: EventEntity! = EventEntity()
The error I get when I try either of those lines with the 'NOPE' comment is 'Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Appname.EventEntity name]: unrecognized selector sent to instance 0x7fa280e16a50' error
Whats going on here?
Thanks in advance!
UPDATE
I have moved performWithSegue to the infoButtonDidPress method, but I am now unable to reference the destinationViewController.
My infoButtonDidPress now looks like this:
func infoButtonDidPress(sender: UIButton){
let eventPressed = eventEntities[sender.tag]
var destinationViewController: UIViewController = self.destinationViewController as EventDetailsViewController
// error: the current VC does not have a member named destinationViewController
self.performSegueWithIdentifier("infoButtonSegue", sender: self)
}
As you discovered, prepareForSegue is happening before infoButtonDidPress is called.
To fix this, instead of wiring the segue from the prototype cell in your tableView, wire it from the viewController icon at the top.
See this: How to wire segue from ViewController icon
Make sure to set the identifier to "infoButtonSegue". Then call the segue from infoButtonDidPress after you have set the value for eventPressed:
func infoButtonDidPress(sender: UIButton){
eventPressed = eventEntities[sender.tag]
self.performSegueWithIdentifier("infoButtonSegue", sender: self)
}
And then, in prepareForSegue pass the value to the destination view controller:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "infoButtonSegue") {
let dvc = segue.destinationViewController as! EventDetailsViewController
dvc.name = eventPressed.name
}
}