Navigation Segue not Working properly iOS Swift - ios

My segue is returning with an error (unwrapping an optional value) from this line > self.navigationController?....
In my code...
let nextScreen = self.storyboard!.instantiateViewControllerWithIdentifier("onboarding-what") as? ViewController
self.navigationController?.pushViewController(nextScreen!, animated: true)
This above code is implemented in my onboarding-start view controller
This is my storyboard set up...
the last view controller has the id of "onboarding-what".
I've read the documentation for the navigation controller but can't seem to find my problem. Does anyone have a solution?

You can use performSegueWithIdentifier rather than pushViewController if you connected them in storyboard
However did you fill "onboarding-what" in the storyboardId field?
pls check this image
Also "onboarding-what" view controller should be instance of ViewController
(There's not default class called "ViewController" only "UIViewController" or "NSViewController" for osX.)

Obviously nextScreen is nil. It is most likely that "onboarding-what" identifier is incorrect

Related

UIViewController initWithNibNamed:bundle: initialized two objects?

I have a UIViewController that I have had in a storyboard for a while with no problems. As my application grew, and I was using that view controller in more and more places, I realized that I should probably make it more portable, rather than have so many segues to it from hither and yon across the board. I've done splits like this before, so I did what I figured was logical here. I selected that view controller, cut it, and pasted into an empty .xib file. After changing each call to performSegueWithIdentifier to an init(nibName:bundle:) and presentViewController, I get a crash, with an object found unexpectedly nil in viewDidLoad()...
I set the value of this object after each init(...) call, just before presenting the view controller. The nil object is called from viewDidLoad(). This is a problem. I just set this, and now it's gone?!
I overrode the init(...) method, and found that self in init(nibName:bundle:) doesn't have the same memory address as self in viewDidLoad(). Also strange.
I overrode the other init() methods, and found that, after I call to present my view, my object is being instantiated again via init(coder:)! The self in here happens to be the exact self where my property is found nil!
The only reason I see for init(coder:) to be called at all is that I am loading my view from a .xib, but I thought this was handled in init(nibNamed:bundle:)? According to the docs, I do indeed get a call to init(coder:) if I'm loading from a storyboard, and doesn't touch the former... It also says that the nib isn't loaded until the controller's view is queried. If I understand it correctly, my view shouldn't get queried until I present the view. As the crash happens only when I present it, the issue likely stems from that.
I'm stuck here. I still need to get this contextual information to the view controller before it's presented. I've even tried making a proxy class to do the instantiating and property setting before presentation, but I still can't shake this second instance! I get one from init(nibName:bundle:), and another from init(coder:). Neither gets presented, and the latter gives me a nil object error. Any help at all in understanding why this is, and how I might work around this bug (feature?) would be much appreciated. Thank you!
Update:
On a whim, I decided to paste the view controller back into the storyboard, separate from the main hierarchy, and try instantiating it by its identifier. It worked! Not entirely sure how, but by George it worked! Now my question is this: Why?? What is so terribly evil and taboo about .xibs that Xcode and iOS won't tell me? I'm not a little flummoxed by this behavior. I'll keep trying with the .xib, if only to keep Xcode from yelling at me about entrance points...
I don't know what dark magic Xcode is doing, but here's two helper methods I wrote to easily instantiate any Storyboard VC - you just need the Storyboard name and VC identifier (optionally, otherwise will initial VC). By splitting up my VCs into many different Storyboards, I avoid dealing with xibs while still keeping things simple. One loads it into a nav controller of your choice, the other just returns it by itself:
struct StoryboardHelper {
///instantiates a VC with (optional) identifier viewController from storyboardName, pushes it to hierarcy of navigationController, and runs setup block on it, animated specifies whether the push is animated
internal static func showStoryboard(storyboardName: String, viewController: String?, navigationController: UINavigationController, animated: Bool = true, setup: (UIViewController) -> () ){
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
let destinationVC = viewController != nil ? storyboard.instantiateViewControllerWithIdentifier(viewController!) : storyboard.instantiateInitialViewController()!
setup(destinationVC)
navigationController.pushViewController(destinationVC, animated: animated)
}
///instantiates and returns a VC with (optional) identifier viewController from storyboardName
internal static func instantiateViewControllerFromStoryboard(storyboardName: String, viewController: String?) -> UIViewController{
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
return viewController != nil ? storyboard.instantiateViewControllerWithIdentifier(viewController!) : storyboard.instantiateInitialViewController()!
}
}

ViewController popped immediately after been pushed in UINavigationController

I bounce in a quite weird issue. When I push a specific view controller for another one, the former get dismissed soon after being showed. When I push it fom the main View Controller, it stays put without any problems. I put breakpoints and the viewDidDisappear is in fact called just after the viewDidAppear.
By smell it look like the second view controller becomes nil in one way, but how is it possible if that is wired to the storyboard?
Has anyone got any idea about what could be the reason for the weird behavior?
The main view controller and the first view controller are both in Swift, the pushed controller is still in Objective-c.
This is how I open the second view controller:
func didSelectRow(indexPath: NSIndexPath, from owner: DestinationsViewController){
if let currentElement=DestinationsContentProvider.sharedContentProvider().stations[indexPath.row]{
print("a \(indexPath.row) elemento \(currentElement)")
let targetModel = currentElement.model
//NSLog(#"targetMetro:%# targetPaletta=%#", owner.targetMetro, owner.targetPaletta);
if ((targetModel != nil) && (targetModel!.myTraffic != nil)){
targetModel!.segueExecute()
}
}
segueExecute is called on the model that is not dismissed. I put a breakpoint on the dealloc and it is never reached.
The only peculiar issue is that in the model I perform the segue on the main controller instead of the actual controller by this piece of code:
mapController.performSegueWithIdentifier("ShowWaiting", sender:self)
Still the same behavior happens even if I manually push the controller by executing:
let mainStoryboard:UIStoryboard!
if (UIDevice.currentDevice().userInterfaceIdiom == .Pad){
mainStoryboard=UIStoryboard(name:"StoryboardiPad", bundle: nil)
} else {
mainStoryboard=UIStoryboard(name:"MainStoryboard_iPhone", bundle: nil)
}
let controller = mainStoryboard.instantiateViewControllerWithIdentifier("Situation") as! StationSituation
controller.model=targetModel;
InArrivoHDViewController.sharedDetailController().navigationController?.pushViewController(controller, animated: true)
without using the segue construct.
Just check whether second view controller used for pushing is a property or not. If secondVC instance is created within the method in which pushing is done, secondVC will become nil after execution of the method.
I fixed the issue by directly calling performSegue on the view controller rather than delegating it to the root controller. For some reason this delegation works if there is the same kind of view controller on the Navigation queue in which you are pushing the controller: I have this construct in another class and I just checked it actually work. Otherwise the effect is the weird one I experienced.
I think, but I may not be sure, that in Objective-c the situation was different.

How to Programmatically Segue to a New ViewController in a New Storyboard

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
}

adding UIPageViewController to a view controller's container view

I'm trying to Add my pageViewController to a container view on my main viewController . For that , I have added these codes
addChildViewController(pageViewController!)
self.sliderView.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
But when I run the app ,it's looks like this :
http://i.stack.imgur.com/0Sf17.jpg
I want to add my pageViewController in the yellow containerView which name is sliderView .
What's wrong with that?
Thanks
Please provide more code as the given example code works pretty well.
Possible causes could be the forced unwrap of your pageViewController. Additionally ensure that the controller is properly instantiated from Storyboard like
guard let vc = storyboard?.instantiateViewControllerWithIdentifier("YourViewControllerID") as? YourViewControllerClass else
{
return
}
sliderView.addSubview(vc.view)
vc.didMoveToParentViewController(self)
You can set YourViewControllerID directly within the Storyboards Identity Inspector

Root View Controller Swift

I have a function in my app delegate which appends an item to an array in my a file named ViewController.swift, and then I want to reload a tableview in that same file. I attempt to do so like so:
let vc = ViewController()
let navigationController = UINavigationController(rootViewController: vc)
window!.rootViewController = navigationController
println(vc.messages)
//1 vc.messages.append(message.data.message as! String)
//2 vc.MessageTableView?.reloadData()
The lines numbered 1,2 are where I set breakpoints. It appears to break after line numbered 2.
The exact error I get is
fatal error: unexpectedly found nil while unwrapping an Optional value
I believe my problem is that I am setting the root view controller incorrectly.
Edit #1
Window is declared up top.
If i run my code like this:
let vc = ViewController()
messages.append(message.data.message as! String)
vc.MessageTableView?.reloadData()
println(messages)
Then I can see that the correct data is put into the array (Which i made global for this scenario) but the table does not get updated in the View controller.
You have to reload data inside your ViewController
Put the reload inside viewDidAppear() or sth like that
It's an error because you just init a controller, but your views is not ready yet, they are being initialized.
After viewDidLoad, you can call your views, but not before.
So that's why your table is nil
Beside that, why do you need to reload your table even when you don't see it, right ?
What is the implementation of your delegate function?
After you put the tableview in the storyboard,You have to connect the tableview to the ViewController.swift.
Control drag from the tableview to the top of the viewcontroller (the yellowcircle) , there will be a black popup , do that two times and for each time click on datasource and delegate.
Then in the viewcontroller.swift file implement the functions they show in this tutorial. You don't have to modify the AppDelegate.swift file!
https://www.weheartswift.com/how-to-make-a-simple-table-view-with-ios-8-and-swift/
if you want you viewcontroller to be the rootviewcontroller al you have to do is click on the viewcontroller in storyboard and then in the utilities-> attributes inspector -> check the box "is initial view controller"
https://www.dropbox.com/s/qfd9jqeos7ueq1w/Screen%20Shot%202015-06-25%20at%207.40.46%20PM.png?dl=0

Resources