I try using a custom segue to configure a destination controller for purposes of passing data and injecting dependency.
Using UIStoryboardSegue for purposes of injecting dependencies and passing data
This way separates a destination controller and configuration code from a source controller.
But Apple's documentation says 'A UIStoryboardSegue object is responsible for performing the visual transition between two view controllers.'
Is my usage the right way?
I suppose there are many ways to solve those problems. A segue is a good way to pass data by calling "prepareForSegue" method. Nevertheless, you don't need it to change data in another controller. If you have some parameters in an instance of a view controller class but not show it, you could just take a reference to it by using something like:
let resultViewController = storyboard?.instantiateViewControllerWithIdentifier("result")
as! ResultViewController
In that code, "result" is the id of a view controller. No segue is required for that. You could just create a callback for an UI element and call this code to get a reference to that view controller. I think this could be a better solution if you don't want to transition views.
Hope this helps,
Related
I'd like to know which one approach is better and why. When passing data, do you use the delegation pattern to pass data between VCs or you create the destination VC in the prepareForSegue from the VC that you are making the segue and setting the modified data directly from that vc? I'm currently using the delegation pattern, but many people I see are accessing and setting variables directly in the prepareForSegue method of the destination VC.
There isn't really much difference. Passing through prepareForSegue is a simpler option, but if not done correctly can create bad links in your app.
prepareForSegue only passes information, but delegation calls delegate methods.
Delegation mostly leaves everything for the delegate to do.
Delegate methods can be called at any time, but prepareForSegue, as the name suggests, is only called before the segue.
Basically, they have the same effect, but take different paths to the effect.
I am trying to pass instance of object from "initial" view controller to "item1" and "item2". I would like to avoid subclassing UITabBarController as it would make containment view controller know "too much".
Is there any good approach to do that using storyboards or code besides subclassing UITabBarController?
I would like to avoid subclassing UITabBarController as it would make containment view controller know "too much".
You should subclass, and your subclass should implement a specific protocol for this purpose. Yhen, the containing VC only knows about that protocol and it's appropriate because it has that direct responsibility.
I am trying to pass instance of object from "initial" view controller
to "item1" and "item2". I would like to avoid subclassing
UITabBarController as it would make containment view controller know
"too much".
The problem here is that the destinationViewController of your segue is the UITabBarController and not item 1 or item 2. This makes your case quite difficult if you don't want to subclass it, because you can't communicate directly between the instances of your initial VC and the two items.
My recommendation indeed would be to subclass, that's the right way to go in this situation (you might want to add a protocol that specifies the communication interface).
Other options are:
somehow give the initial view controller access to instances of item 1 and item 2 (you'll have to do a lot of this setup in code since Storyboards don't give you the power to do it all completely in IB)
use NSNotification and pass the instances as userInfo (not very elegant but might be the quickest solution for your isse)
store serialized versions of the instances that you want to pass in NSUserDefaults and load them in item 1 and item 2 (might be a lot of overhead)
I'm using a storyboard. Let's say I have a view controller that's named MYviewController.
In - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender; I would like to substitute the view controller that I'm segueing to, by one of its child, for example: MYviewControllerChild1 OR MYviewControllerChild2. The child that's segued to depends on the sender parameter.
These view controllers have the same scene (in the storyboard). Only their behaviour is slightly different.
I have a tableView that shows the user the settings of the application. When he clicks a cell, it segues to a viewController where he can modify the value of some setting. Some of theses are alphanumeric, others are numeric. Depending on which cell is clicked, I'd like the input viewController to format the value accordingly (if it's a decimal value I'll use a NSNumberFormatter for example).
Is that possible?
As mentioned in comments to your OP, I believe you should handle this kind of scenario in one viewcontroller.
However, if you insist on using separate controllers, maybe because you think the functionality will be expanded later down the line and therefore add more diversity, you need to handle this by creating multiple storyboard scenes - one for each child controller.
The destination view controller in prepareForSegue is imposed by the viewcontroller at the end of the segue in the storyboard. I don't think there is any way to override that.
As described, your problem isn't really a good candidate for a storyboard. If you use a storyboard you will have to create and sync multiple scenes. Several possible solutions::
Create multiple storyboard scenes and invoke them manually via performSegueWithIdentifier.
Use a nib file instead of a storyboard for this scene. You can use a single nib file since the view controller is created outside the storyboard with [[VCClass alloc] initWithNibFile: bundle: You can create the appropriate view controller class and pass the same nib file to all instances.
Use a single storyboard scene and view controller and pass in typing information in your prepareForSegue.
In my application I created a container view(called ContainerViewController) on the top of an another view(called GameViewController,where I keep the game logic and api callbacks).I also have other views and an api class.My container view contains 3 views and I am trying to pass some objects to one of my container view(VC1). Since GameViewController is only connected to ContainerViewController(meaning there is no segue directly, so I can't use prepareforsegue and I can't use presentViewController, since they childViewControllers), I can't pass data.
I also tried just getting the values from my deserializer class(inside vc1). The problem with that was the VC1 gets called before.
my question is, how can I set values of VC1 from my callback inside the GameViewController?
This is what my storyboard looks like:
Thank you.
You can do it many ways:
1st way : You can pass the data using Notification.
2nd way : You can create a separate singleton data model class to store your game data. Then you can access the object of that class among your view controllers to set the properties in view controllers.
The way I am designing my code, with several view controllers, that interact, I have the need to pass data between the view controllers. The way that I am doing it is to "pass a reference", make a pointer, to the target view controller in as a method argument like below:
-(void)aMethodToSetUpInterfaceElements:(UIViewController*)targetCV
Is there anything wrong with this, or do I need to watch out? It works well on a functional level, but what about the design?
There's nothing really wrong about this.
If it works for you, than it's ok. Just make sure to have a weak reference to the view controller, otherwise you could have a memory leak with retain cycle. Read this for more information: http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html
Speaking about design, it's really depends of each case. I could't say preciselly because you didn't give more informations about the funcionality that you are trying to achieve.
Maybe if you want to make your code more generic, to be used in other places or projects, you might consider to perform a delegate to your view controller, but this depends of your views hierarchy and its design. To see more information about passing data between viewControllers, please see this: Passing Data between View Controllers
I don't think it is a good idea to pass a view controller in order to transfer its data if you don't have enough reasons. I tend to exposing the minimal knowledge to another object.
For example, say you have two view controllers controllerA and controllerB.
If all you need is just to pass some data from controllerA to controllerB, you pass the data, which might be a NSData, a NSArray, a NSDictionary or your custom data structure. You should not pass the whole controllerA as an parameter to controllerB. Although you can access the data by using the controllerA.data getter, you have exposed too much knowledge about controllerA to controllerB, which may unconsciously ruin your design by increasing the coupling between controllerA and controllerB.
If you are aiming at handling the view transitions, that may be a good reason to pass a view controller as the parameter. So that you can make good use of its -presentViewController:animated:completion: to present a modal view, or push it into a navigation controller, or you probably want to get a reference to its view property and customize your own UI presentation.