I encountered a crash while testing my app. The following image is my storyboard:
I have the code in View Controller:
#IBAction func unwindToHomeScreen(segue:UIStoryboardSegue) {
}
The view of "Add new Item" have a "Cancel" button, I controlled-drag it to the "Exit" icon at the top and link to unwindToHomeScreen, it works fine.
The "Add new Item" has a class AddTableViewController and the code I wrote inside:
#IBAction func save() {
// Execute the unwind segue and go back to the home screen
performSegueWithIdentifier("unwindToHomeScreen", sender: self)
}
I controlled-drag the "Save" button to the func, but the app crash when I click the button
I can use dismissViewControllerAnimated(true, completion: nil) instead, but I just wonder why performSegueWithIdentifier can't work?
I read the code at dropbox.com/s/hpybgg9x67rtqng/foodpinstatictable.zip?dl=0 and try to make one and using performSegueWithIdentifier like this example for practicing, I didn't see the segue identifier at her, what is the difference?
You haven't actually given that segue an identifier. unwindToHomeScreen is a function that you can call; what you're looking for is your segue identifier, which is set in Interface Builder like this:
In this example, I have a button wired to the next view via Interface Builder like you describe ("Interface Builder") and a button that is wired to this IBAction in my view controller ("Programmatically"):
#IBAction func goToNextView(sender: UIButton!) {
self.performSegueWithIdentifier:("go", sender: self)
}
In any case, what you're missing is the actual identifier, which can be set in the attributes of a segue created in Interface Builder.
Swift 4:
Sometimes we must clean the build folder and then try again.
Worked for me after ctrl-dragging the new segue and giving it a name, then using it programatically as:
performSegue(withIdentifier: "goToMyNewViewController" , sender: self)
I found that because I renamed my view controller, I needed to delete and recreate the segue.
A possible issue with iOS 12 and earlier (iOS 13 seems not to suffer from the same issue) might come from the fact that performSegue(withIdentifier:,sender:) is called from the view controller viewdidLoad() callback.
You absolutely must invoke it from the viewDidAppear(_ animated: Bool) callback in order to avoid the question-mentioned crash.
That will certainly save hours of hair-puling…
in my case reorder the Embed in
Tab bar controller
Navigation controller
vc (contains button - tapping button initiates a "show, e.g. push" segue)
Too fix the title in the navigationBar
I had the same issue.
All I did was:
I selected the segue indicator in the storyboard.
Deleted it.
Then created a new segue with the same identifier. Boom, it works.
I had it all wired up correctly. It was just that the viewController I was segueing from, was NOT instantiated from the storyboard. I had it instantiated pragmatically.
I initially had it written as:
let vc = DeviceVC()
Had to change it to:
let sb = UIStoryboard(name: "Main", bundle: Bundle(for: DeviceVC.self))
let vc = sb.instantiateViewController(identifier: "DeviceVC") as! DevieVC
for me --> click on the relation-arrow between view controllers and then select attribute inspector, there is identifier give name and select push class done...
Related
Pardon me for beginner's question.
I know I can switch to another screen (ViewController) like this
self.performSegueWithIdentifier ("SecondViewController", sender: self)
but I can't seem to find where to assign my 2nd screen the id, I just find Storyboard ID, is that it?
I've already tried, only received a crash with the following error:
Receiver () has no segue
with identifier 'SecondViewController'
Any idea? thanks
Segue Identifier is not the same as storyboard ID, storyboard ID used when you want to create a View Controller based on that specific storyboard -and it has to be unique, unlike the segue identifier-.
If you already know how to create a segue, you can skip this part.
Adding a segue between two viewControllers:
From the Interface Builder, press the ctrl and drag between the two View Controllers that you want to link (make sure that you are dragging from the view controller itself, not the its main view). You should see:
Choose the "Show" -for instance-, the output should look like this:
As shown above, the arrow that surrounded by the red rectangle is the segue.
Additional note: if you selected the "Show" option, you have to embed your first view Controller in a Navigation Controller (select your first viewController -> Editor -> Embed In -> Navigation Controller), the output should looks like:
Because the "Show" means pushing into a navigation controller stack.
Assigning an identifier for the segue:
Select the segue, from the attribute inspector you'll see "Identifier" text field, that's it! make sure to insert the exact same name that used in performSegueWithIdentifier.
If you don't know where to find the attribute inspector, it is on the top right looks like:
Furthermore:
For adding multiple segues from one View Controller, follow the same process (ctrl + drag from the first controller to each other View Controller), the output should looks like:
In this case, you might face the issue how to recognize which segue has been performed, overriding prepare(for:sender:) method is the solution, you can make the checking based on the segue identifier property:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "firstSegueIdentifier") {
// ...
} else if (segue.identifier == "secondSegueIdentifier") {
//...
}
}
which would be the name that you have added to the segue in the storyboard.
In your code
self.performSegueWithIdentifier ("SecondViewController", sender: self)
the string "SecondViewController" is looking like storyboard id . At the same place you have to write the segue identifier , not storyboard id .
Follow the Screenshot and assign segue identifier name by clicking on the segue on right top bar field. you can do like this
self.performSegueWithIdentifier ("WriteSegueIdentifierName", sender: self)
Similar to the answers provided, here's what it would look like in Xcode 12:
Select the segue link in Main Storyboard view
Navigate to the Attribute Inspector and add an Identifier (if one does not exist)
Add the Identifier to your code. Done!
When you link a View controller to another View controller in the storyboard, in the link between them you need to assign a segue identifier i.e "SecondViewController" only then your code will work.
Alternatively, you can also show another view controller through storyboard id using self.storyboard.instantiateViewControllerWithIdentifier("//storyboard id of that view controller") and then either use present/show view controller.
You can initiate viewController like this:
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Login")
self.present(viewController, animated: false, completion: nil)
Show Xcode screenshot
Click on Present Modally segue label... and on the Attributes Inspector input Identifier
I've created a typical unwind flow from my view controller #2 to back to view controller #1 using a programmatically created button using the segue to Exit technique.
I have trace statements that confirm that the button code is executing perfectly and that the #2 performSegueWithIdentifier func is being called with the correct segue ID, but nothing happens.
To clarify:
I've connect the view controller #2 to the Exit and confirmed the segue ID is exact in all places. I traced the #2 identifier in the #2 performSegueWithIdentifier func and it matches perfectly.
As I understand it, I no longer need to use the dispatch fix with the current version of 2016 XCode. I tried it anyway and nothing worked. There is no crash, just no unwinding.
Somehow the unwind technique isn't reversing using this Exit technique. Any ideas?
I've been following the tutorial here: https://spin.atomicobject.com/2014/12/01/program-ios-unwind-segue/
CODE VC #2:
// action func wired to button, fires perfectly
func unwind(seg:UIStoryboardSegue!) {
self.performSegueWithIdentifier("unwind", sender: self)
}
In VC1 you need a function:
#IBAction func unwindToVC1(segue:UIStoryboardSegue) {
}
Then in your storyboard ctrl drag from the yellow view controller icon to the Exit icon and select unwindToVC1: from the pop up
Give the unwind segue an identifier, say unwindToVC1
Now, in VC2, create your button touchUpInside handler:
func buttonTapped(sender:UIButton) {
self.performSegueWithIdentifier("unwindToVC1")
}
when you set up your button programatically, add this method as the action handler:
button.addTarget(self, action: "buttonTapped:", forControlEvents: .TouchUpInside)
Move the unwind function to VC1. Leave that implementation empty or perhaps put a print statement to see if its coming to that function.
Make sure that in the storyboard there is a unwind segue created with identifier "unwind"
Add a button action func buttonAction:(button:UIButton) that calls performSegueWithIdentifier("unwind"...) in VC2.
Set the buttonAction as the action for the button created programatically.
I simply want to know how to segue to a new view controller in a new storyboard without having to create the new view controller programmatically.
The Scenario:
I have one view controller that's created entirely in code and the system thinks I'm in Storyboard A. I want to segue from this view controller to another view controller that's contained on Storyboard B.
I could create a segue attached to a storyboard reference (which is a great suggestion) if this view controller was created with Storyboard. But it's in code, so I can't do this.
My other option is to make the next view controller be totally created in code so that I can present it without using segues. That's a pain, but will work.
My third option is to initialize the new storyboard in code, initialize the new view controller in code using a storyboard identifier, and then use the navigation controller to segue to it.
If there are other options I'm not aware of please include them below!
This piece of code allows you to segue to any viewController anywhere in your application while still being able to build your viewController with storyboard.
func settingsButtonPressed(sender:UIButton) {
let storyboard = UIStoryboard(name: "AccountLinking", bundle: nil)
let linkingVC = storyboard.instantiateViewControllerWithIdentifier("AccountLinkingTable")
self.navigationController?.pushViewController(linkingVC, animated: true)
}
So many hours saved thanks to this little function.
I would urge anyone reading this to take a look at the Storyboard Reference introduced in Xcode 7 to achieve this instead of loading the storyboard programatically.
You can override the below function to override the segue call.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var destinationController = segue.destinationViewController
}
In Swift 2, Xcode 7.1
As the image above, TabBarController will be the main view. Anonymous user can go to the home tab, if they click on the "Me" (Profile) tab, I want the app will pop up the new login segue (navigation controller). User need to login 1st before they can go into the "Me" tab.
Currently I have override the TabbarControllerDelegate in the TabBarController class, which as below (I use Parse, so user = PFUser.currentUser(), Parse will cache the user):
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
if (viewController is MeViewController && user == nil) {
print("login \(viewController)")
// How could I go to the Login Segue from here?
return false
} else {
return true
}
}
How could I achieve my goal from here? Or any better advice? Btw, I am not able to use performSegueWithIdentifier with the TabBarController class unless I use it within the ProfileViewController class (UIViewController) to achieve it. But if I did that, the app will display the view in 'Me' Tab first then go to the 'Login' segue, which is not what I wanted
It will be great thanks for any advices
If you want the user to not be able to go to me before login, you can just do a check with a static bolean which will be initialize in app delegate.
Then if the bolean is set to false (default value), you can invoke the your login popup.
No point here to perform a segue, just put an identifier on the view in the storyboard (identity inspector => storyboard id) and then you can invoke this particular view of the storyboard like this :
let SB = UIStoryboard(name: "MyStoryboard", bundle: nil)
let controller = SB.instantiateViewControllerWithIdentifier("MyId")
self.presentViewController(controller, animated: true, completion: nil)
Segues are only for views which are linked to each other, i personnaly almost never used them.
I recommend that you make the login UINavigationController segue come directly from the UITabBarController instead of on the "Me" controller. This is because you can't modally present your login controller through the "Me" controller if its not on the screen.
Give the segue an identifier (eg. "my-identifier"):
Click on the segue in the storyboard editor and fill in the identifier field in the right sidebar.
After this is configured correctly, the following code will perform the login segue (note the use of tabBarController since you should have the segue configured from the UITabBarController:
tabBarController.performSegueWithIdentifier("my-identifier", sender: self)
I´m making an app in Xcode V6 and I´m trying to send a variable to the main viewController when i close my modal view which appeared after I press a button on the main viewController.
I open my app and see storyboard1 with a button1, I click button1 and a storyboard2 appears in modal view. When I close the modal view I want to send a variable created in storyboard2 to storyboard1. It´s the sending I have problems with.
I have this code:
Storyboard2:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var sendValues = "This is a title!"
let destinationValues = segue.destinationViewController as ViewController
destinationValues.recieveString = sendValues
}
Storyboard1
var recieveString: String = ""
println(recieveString)
I try to print it when I press a button but nothing happens..
when I segue between the views I try to print it but nothing is printed, It´s like the segue did´t work...
Any ideas?
The pattern often used in iOS development for this kind of case is delegation. Basically you pass your original (presenter) view controller as an object that conforms to a protocol defined by the presented view controller. Then from the presented view controller you can modify the presenter's variables.