I have a project in which I have a storyboard. The storyboard contains several view controllers. I'll simplify it and omit the unnecessary details. Within a Navigation Controller, there are several UIViewControllers hooked up with segues. (see screenshot below...)
From left to right on the bottom row it goes Navigation Controller ➞ VC1 ➞ VC2. VC1 also has a manual segue to VC3 on the top row which goes VC3 ➞ VC4. VC1 is the starting view controller of the app. There two segues connecting from VC1. The segue from VC1 ➞ VC2 is the primary segue and from VC1 ➞ VC3 is the secondary. The secondary segue will be called programmatically when the user runs the app for the first time as a sort of welcome/getting started sequence.
I set this up going off of this post here, referencing the second most upvoted post in which the user suggests a segue between the starting VC file itself and the view of the other VC and then calling performSegueWithIdentifier.... here is the problem.
When running this app, there are no compile-time errors. It all looks good. It loads up, and I have this set to go in the view did load, which for now I am forcing it to run as if it were the first time like so...
override func viewDidLoad() {
super.viewDidLoad()
let firstVisit = true
if firstVisit == true {
self.performSegueWithIdentifier("welcomeSegue", sender: self)
}
// Do any additional setup after loading the view.
}
So it loads up. I can tell it attempts to show VC1 before VC3 promptly gets pushed on top as desired. VC3 is displayed, brilliant. The issue occurs when I press the one and only button on VC3 that should perform a typical segue from VC3 ➞ VC4. This is when I get the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<X.VC1>) has no segue with identifier 'welcomeSegue''
Now the strange thing to me that I cannot figure out is that, even though VC3 has been properly presented, it is VC1 that this error originates from as denoted by the Receiver (<X.VC1>). I'm stumped. All of the errors I have found online show other solutions that have not worked for me. If you don't believe me when I say I know the spelling is right, A) It properly loaded the view controller, B) here is a screenshot anyway.
I DUN GET IT :[
Let me know if you have advice. Thanks all.
** AGAIN, JUST AS A REMINDER, THIS APP DOES PROPERLY LOAD AND DISPLAY VC3 AS IT SHOULD. THE ERROR OCCURS AFTERWARDS WHEN I ATTEMPT TO SEGUE TO VC4 BUT THAT SEGUE IS NORMAL THROUGH INTERFACE BUILDER WITH NO IDENTIFIER BECAUSE IT WILL NEED NO LINK TO THE CODE AS THE SEGUE TO VC3 DOES.
EDIT: Here is a sample project that functions properly. I cannot distinguish a difference that sets mine apart.
EDIT #2: I admit to making a dumb mistake. The marked solution has found it and corrected it and the project now functions as desired. Thank you all.
I study your project and found that you assign wrong class to your VC4 as shown in below image:
Just remove that HomeVC and assign new class to it and it will work fine.
It seems like that you have not set segue identifier. performSegueWithIdentifier method trying to called welcomeSegue. but its don't available so crash happen.
To removed the following crash, followed the steps.
Step 1 : Tap on segue between two UIViewController. like as
Step 2 : Now check property of that segue at right side of panel. where write identifier name as welcomeSegue.. like as
Now run your project, you will face any crash..
Related
Now I created a new project to test unwind segue.
In Storyboard the story entry is on VC0, a button in VC0 goes to VC1 (modally), a button in VC1 goes to VC2 (modally).
VC2 has a button to dismiss itself and in the function it looks like this:
#IBAction func btnDismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
in VC1 I added an unwind function as follows:
#IBAction func unwindSecondView(segue: UIStoryboardSegue){
print("unwinded")
}
Then in storyboard I linked VC2's exit icon to unwindSecondview as action.
It works pretty well, however after I clicked "dismiss" button in VC2, VC1 appeared briefly and jumped back to VC0.
??? Anything wrong that caused jumping back to VC0?
--------------Initial question -----------------
I'm new to iOS and got a little confused for how VCs are created and activated.
Say I created 2 ViewControllers in my single view app. MainController(VC_M) and SettingsController(VC_S). I added the segues in storyboard, a setting button in VC_M goes to VC_S, VCS collects information, writes to standardDefaults, then ok button goes back to VC_M and refresh its view.
When I try to preserve some information in VC_M, I found that after I click ok button in VC_S and go back to VC_M, VC_M gets recreated and viewDidLoad() gets called. In the debugger, it shows the VC_M object (self) now has a different address in memory, so seems it's another instance of the class.
Is this a normal behavior? It's best that the old VC_M object gets saved so some data doesn't need to be reloaded. Initially I thought I could put some data loading stuff in init(), but when VC_M gets re-created init() got called, too. Some older posts suggested that ViewDidLoad() should not be called again but rather ViewDidAppear() should get called, but I'm not sure if it's the same case now.
In my case is it better to just use standardDefaults to reload everything, or is there a different kind of segue I should use? (I used push segue).
I have the following scenario: I have a view controller and want to navigate programmatically to another view f.e. to give the user the ability to change settings.
So I have VC1 and VC_settings and a present modally segue between those controllers. I gave the segue an identifier and call it like this:
performSegue(withIdentifier: "SegueToSettingsView)
Ok, that works without any problems. The settings view is opened and I can navigate back to VC1.
Now I want to have the same functionality in another view controller VC2. I want to reuse the settings view but the problem is that the segue is already connected between VC1 and VC_settings and I can't connect a new one for VC2.
And if I try to call the existing segue with the coce above in VC2 then the app crashes.
In swift it is possible to create segues from multiple views two one viewcontroller. Here I have set it so there are segues from VC1 to Settings and VC2 to settings which should work.
Hope it helped
Since you have VC1 and VC_settings connected with segue named "SegueToSettingsView" also the perform selector is working fine.
As per your need make another segue from VC2 to VC_Settings and give a different name for it. then make use of below code to perform segue.
performSegue(withIdentifier: "SegueToSettingsViewFromVC2")
Steps to make segue:
Then select the connection and set identifier
I segue from one Storyboard where the View Controller is written in Objective C to another Storyboard where the View Controllers is written in Swift 2 and it goes through fine.
However, when I click fire the next segue in the second Storyboard, I get the following error:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'record'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
This is the code that calls the next segue in Swift 2
self.performSegueWithIdentifier("record", sender: nil)
The initial view in the second Storyboard is embedded in a Navigation Controller as well.
Also worth noting, I tried without the first storyboard and my app going directly to the second storyboard, and it finds the segue fine.
Any ideas on what could be causing the problem?
Choose the segue, go to its Attributes inspector and change the Kind from push to Modal. Let the presentation and Transition remain default.
This will work fine for you.
But if you want the segue of kind 'Push' then the first View controller which is written in Objective-C should be embed in Navigation Controller.
I have a few views embedded in a navigation controller.
I've created a few segues (some from buttons to other view controllers, some from one view controller to another one.
for example I have a segue (Show) from one button to a view controller called name2, when I press the button it works great, but when I try to call it programmatically the app crashes and gives an error.
This is how I call the segue on ViewController1
self.performSegueWithIdentifier("name2", sender: self)
this is from ViewController1 to ViewController2
I also have a segue that is connected not to a button but from vc1 to vc2, gives the same error.
This is the strange error I get:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (ViewController2) has no segue with identifier 'name2''
I tried cleaning the product and also reseting the simulator.
A screen shot of my storyboard
A screen of the identity inspector of viewcontroller1 (it is actually called ViewController in my project)
A screen shot of the segue (name3)
The options of the segue :
Edit:
I found that when I connect a button as an IBAction and then call performSegueWithIdentifier("LogIn", sender: self) from the button it works correctly.
Any help?
Do not connect your Button in Storyboard Editor to the other segue (when you want to call the performWithSegue function within your ViewController1) - just connect the first ViewController to the second One.
Then you can use
self.performSegueWithIdentifier("name2", sender: self)
within your ViewController1 class.
When you set the Segue from one view controller to the other, ensure that you have correctly set the class - see image:
UIStoryBoardSegue was what mine needed.
The error says that you're looking for a segue in ViewController2 but your question states that the segue comes from a button. That would explain why it can't be found.
Try to remove the segue identifier ( name ), build ( cmd + b ), then set the segue identifier and compile. ( in storyboard of course )
Ok the answer is that I'm pretty dumb,
Whenever I was creating new ViewControllers, I was subclassing ViewController which was my first ViewController, instead of UIViewController which made it run recursivly.
I have a fairly simple app thats a game for small children. There is a main screen and 5 separate levels. 3 of the 5 levels are made up of more than one VC where actions take place in the first VC in that row then code calls a modal segue to the next one in the line and so on till it reaches the end of the row and a modal segue is called linking back to the main screen. The levels that have only one VC just perform actions then segue back to the main VC.
Every segue in the app in modal.
Also every page (VC) has a home button that will segue to the main page if pressed
I set this all up in the StoryBoard and visually everything works as Id expect but when adding sound I realized that there seems to be a major problem.
If I now understand correctly (and maybe I dont) modal segues dont actually replace the current VC with the newly requested one but rather slide the newly requested one over top the original and make it the visible display.
Currently I go from main to level 1. Level 1 does some stuff and plays some sounds that repeat via a timer. If I segue back to main visually everything is fine except the sounds being played by the timers in level 1 VC continue to play and xCdoe give me the following error quite a few times
2013-01-21 22:16:07.901 TTBetaDev[678:c07] Warning: Attempt to present <MainMenuViewController: 0x7e02f40> on <BonusViewController: 0x7ecbfa0> whose view is not in the window hierarchy!
Below is a screenshot of my storyboard in case I havent explained the layout well enough.
How should this be set up to allow the navigation I would like? A what steps will I need to take to apply that to the what I already have built in the storyboards? Or will I have to re-do all my storyborad work?
I tried apples VC documentation but I couldnt understand what relates to what Im trying to do.
COuld someone please help explain this to me
You have segues going forwards AND backwards. You shouldn't do this.
e.g. Look and Main and VC 2.
You have a segue going from Main to VC 2. This means that Main will present VC 2 as a modal view controller.
When Main does this though it is still on the stack underneath VC2.
Then you have a segue from VC2 to Main. This means that VC2 will create a new Main and present it modally too. If you continue using the app you will have multiple instances of main and all the other VCs and memory consumption will rocket.
What you need to do is delete ALL the segues that go backwards. (i.e. like the one from VC2 to Main)
Then when you want to get back to main from VC2 you have to dismiss VC2.
i.e.
in Main...
//present VC2
[self performSegueWithIdentifier:#"VC2Segue" sender:nil];
//dismiss VC2
[self dismissViewController:vc2ViewControllerInstance];
or in VC2...
//dismiss VC2 from itself
[self dismissViewController:self];
The main thing though is that you can't use segues to go backwards.
TL:DR
Nothing should segue INTO Main. Any segues that go into the left hand side of main should be deleted and dealt with properly.