I have used protocol to send data between two view controllers without using storyboard.
ViewControllerB * viewB=[[ViewControllerA alloc] initWithNibName:#"ViewControllerB" bundle:nil];
viewB.delegate=self;
[self.navigationController pushViewController:viewB animated:YES];
How to impliment this with storyboard.
How to impliment this with storyboard.
There's less need to create a protocol to communicate between two view controllers when you use a storyboard. Typically, you'll use storyboard segues to transition between view controllers. When a segue is triggered, the current view controller will get a -prepareForSegue:sender: message, which has the segue as its first parameter. The segue has references to both the "source" and "destination" view controllers, so you can get a reference to the new view controller (the destination) and pass it whatever data you like at that time.
If you do still want to make the current view controller the delegate of the destination and let them use whatever protocol you can dream up, you can set the new controller's delegate in -prepareForSegue:sender:. The rest (creating the protocol, implementing it, etc.) is exactly the same as you've always done.
Related
What would be main difference between using instantiateViewControllerWithIdentifier and performSegueWithIdentifier ?
I think that performSegue.. is used for normal pushing of viewControllers as instantiateViewController is used for some kind of modal showing of viewController and then dismissing it when used.
Since there are also modal and custom push in storyboard I'm not sure about my theory so if anyone could explain when to use which one ?
Thanks.
The difference is that performSegueWithIdentifier is used to transition to a specific view controller that is connected by a segue in interface builder (Transition1 in my screenshot).
instantiateViewControllerWithIdentifier can be used to instantiate any view controller on a storyboard, regardless if it's connected by a segue or not (Transition2 in my screenshot).
Push, modal, or any other custom transition could be used for either scenario.
instantiateViewControllerWithIdentifier can also be used to instantiate view controllers from separate storyboard files. A segue has to be within the same storyboard file.
The segue identifier used in performSegueWithIdentifier needs to be set in interface builder.
The view controller identifier used in instantiateViewControllerWithIdentifier is the Storyboard ID field in interface builder.
For my app, I want to have a few different instances of the same view controller. For now, I am just creating a new instance like this:
iSafeViewController *tab = [[iSafeViewController alloc] init];
[tab setModalPresentationStyle:UIModalPresentationFullScreen];
[tab setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:tab animated:YES completion:nil];
Great. And since this is done in the iSafeViewController class anyway, I have another button that currently just dismisses the latest controller on the stack.
- (IBAction)closeTab:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Okay, however, I really want to be able to go back to these instances. So, I have two questions.
Does dismissViewControllerAnimated remove that controller's instance from memory. If not, is there a way I can re-present it.
There is probably a better way to navigate through viewController instances then presentViewControllerAnimated. At the very least, is there a better way to create new instances of one's viewController and be able to navigate to each of them, hopefully not in a stack. In other words, if there are three viewController instances, is there a way I can go from the third to the main one?
Any ideas would be appreciated. Thanks.
"Does dismissViewControllerAnimated remove that controller's instance from memory? If not, is there a way I can re-present it."
Calling dismissViewControllerAnimated does not explicitly remove a view controller from memory, but if no other part of the code is storing a strong reference to the view controller, once the presenting view controller dismisses your VC, it may be deallocated as per the normal memory management system.
So if you ensure something in your code has a reference to your view controller (aside from the VC which is presenting it modally), it won't disappear after being dismissed, and yes this means you can re-use it.
As for "random access" to view controllers: you could use UINavigationController and use methods like popToViewController:animated: and multiple calls to pushViewController:animated: (without animation!) to create the effect of travelling to arbitrary view controllers. This feels like a bit of a hack.
Alternatively, and preferably, you could write your own custom container view controller. This is a view controller that deals with presenting other view controllers. See Apple docs.
Here's a good WWDC video on the subject: Implementing UIViewController Containment
Further reading:
Container View Controller Examples
http://subjective-objective-c.blogspot.co.uk/2011/08/writing-high-quality-view-controller.html
Custom container view controller
I want to move from one view controller to the next, using code. I have this:
[self.navigationController pushViewController:ViewController2 animated:YES];
This code is used in the first screen that launches. I want it to push (under a certain condition) to the NEXT view controller which is called ViewController2. ViewController2 already exists (its a storyboard project). But the current view controller doesn't know what ViewController2 is in the above code. How do I 'get' or 'access' ViewController2? It already exits, with .h and .m files, but how do I call to it!?
if you're using storyboards, you can just access it through its identifier like this:
ViewController2 *viewController2 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController2"];
Make sure to properly set its identifier to "ViewController2" or whatever name makes sense.
This isn't the way that you normally push a view controller when you're using storyboards. You should have a push segue set up in IB and the use performSegueWithIndentifier:sender: to go to the next controller. You should also implement prepareForSegue:sender: where you can get access to both the source and destination controllers. This is the method where you typically provide any data needed for the second view controller to do its job.
I decided to give the use of storyboards a go in my current iPhone app. I am facing a bit of a problem. I really need to reuse my UIViewController instances.
What do I mean by that? Well, for example I have a table view controller. When I tap a cell, another view controller is loaded from the storyboard and pushed onto the navigation controller stack. This all works well, but it takes about half a second to a second each time this view controller is loaded. Before I was using story boards I simply solved this problem by caching the created instance so the second time you tap a cell the view controller can be immediately shown.
By caching the created instance I mean something like this:
if (!cachedInstance) {
cachedInstance = [MyViewController new];
}
[self.navigationController pushViewController:cachedInstance];
Does anyone know how to accomplish this using the storyboard? Thanks in advance.
If you are using segues, you will need to create custom segues in order to use a cached view controller like you did before. Otherwise, the typical "push" segue will create a new instance of the view controller for segue.destinationViewController. If you write a custom UIStoryboardSegue class and use custom segues you can override initWithIdentifier:source:destination: and put your cached view controller in for the destinationViewController, and then override perform to use the classic pushViewController call.
That is how you handle the segue if you are really intent on using them. I would just skip it though, unless you really want the fancy arrows to lay everything out on your storyboard. If you skip it you can just instantiate the view controllers into the cache and then push them on just like you did before.
If your question is more about locating a view controller inside a storyboard then you can use:
UIViewController *vc = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"Some View Controller"];
Then you can save that to your cache and push it like you did in your example code.
Hope that helps.
SliderDemoController *sliderDemoController=[[SliderDemoController alloc] initWithNibName:#"" bundle:nil];
[self.navigationController pushViewController:sliderDemoController animated:YES];
i implemented this method using storyboard. but this method is not working. i want to open new controller in table view cell.
If You want to access any view controllers which is in story board then you should use UIStoryBoard class.If you not sure about how to do that so, Here is the link for apple document about UIStoryBoard and use the method + (UIStoryboard *)storyboardWithName:(NSString *)name bundle:(NSBundle *) storyboardBundleOrNil to access your storyboard.
Access your view controller with the method - (id)instantiateViewControllerWithIdentifier:(NSString *)identifier and use the returned view controller object.Hope this helps you....
You don't need to query the UIStoryboard object -- setting up transitions between view controllers is what storyboards do automagically. And with storyboards, you don't need to implement tableView:didSelectRowAtIndexPath: either.
If you haven't already, define a segue from the (prototype) table cell to the destination view controller (looks like that's SliderDemoController for you) by control-dragging. (Choose the Push segue type.) For functionality equivalent to the non-storyboard code you posted, that's all there is to it -- now tapping any row in the table will push in a SliderDemoController.
However, you probably want to configure that SliderDemoController based on which row was selected, right? Then, in your table view controller, implement prepareForSegue:sender:. There you can get a reference to the destination view controller (from the segue parameter) and set it up however you like.