Passing references to viewControllers to other viewControllers cocoa touch - ios

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.

Related

What is a good approach to pass data through containment view controllers

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)

Who should create the ViewModel in iOS MVVM?

I am trying to develop a simple app to understand MVVM but I don't get it really well. I've read some articles, but they are a bit different:
View in different class MVVM
In this example the view is not the ViewController itself, it is a class that contains all the details of the view and it is an abstraction for the VC.
The ViewController creates the ViewModel with some data the it retrieve from DB, Network..
The ViewController talks with the model and manage the ViewModel to update the view.
ViewController is the view MVVM
In this example, the viewController is the view, it does not need other class. The viewModel is not created by the viewController, and the ViewModel of the next ViewController is created by a ViewModel. The ViewModel also has an instances of the Model, so if it needs to retrieve some data, it has instances of the DB, Network..
I don't understand well some things. If the viewModel is retrieving data from Network with asynchronous tasks and I want to display an spinner and get data for fulfil the view. Should I user blocks, KVO or delegates? If I use delegates, the view implements ViewModelDelegate Methods, would be that correct? Am I coupling view with viewModel? I am confused at this point.
If I have a firstViewModel that creates a new secondViewModel for a new pushed SecondViewController,and FirstViewController has to update its view before the user pops the pushed SecondViewController. In this case firstViewModel has to observe secondViewModel and notify the changes to firstViewController once popped, doesn't it?
I also have a question about ViewController creation. ViewControllers are the attendants of next ViewControllers creation? If I create an object that manages ViewControllers creation and navigation should I pass this object over viewModels?
I know they are very similar, but I am confused about which way I should implement and how. There isn't much information and examples about iOS MVVM.
I am not using Reactive Cocoa yet because I want to understand this pattern well first. Though it is in my TO-DO list.
Thank you!
It really depends on why you're using MVVM. I'm doing it right in the middle of the two cases you mention, actually. Here's the two reasons for MVVM usage:
First, you may be using MVVM because you want to organize your code in a way that pulls the logic out of the VC and keeps it clean. In this case, you're using a ViewModel in good OOP form and it's perfectly find to have the VC create it.
On the other hand, you may be intending on UI testing your VC's and therefore want to introduce mock ViewModels. In this case, you want to be handing the ViewModel to the VC. (i.e. dependency injection)
In my view, either is justifiable. You might even have multiple needs in one app. Therefore, I keep things flexible. My approach is to create the VM in the viewDidLoad() method of the VC only if it doesn't exist yet. This allows me to use my normal VM and to do create it (neatly) in my VC, but if I ever need to override it (unit testing, UI testing, alternate view style), I can, too.
The issue comes from the fact Cocoa apps, are by definition using MVC, and you have to try and make MVVM work with the underlying ViewController structure.
I haven't looked at MVVM in iOS, but have done a bit using Xamarin.Forms, where the View is just the XAML code, the view model interacts with the View and the Model. Under Cocoa apps, it doesn't really matter too much how you do the ViewModel part, but looking at your links, I think the second approach is closer to a purer MVVM approach.
I suggest you download the code in the link and have a look to get a greater understanding?

iOS storyboard and injecting properties

I'm using iOS 5 storyboard for the view control hierarchy. The problem with this is that I have a few shared controller classes that handle the business logic that I would need to inject to the view controllers. These controllers are initialized and kept in the app delegate.
For instance, I have a controller encapsulating Dropbox interaction that I'm using in some of my view controllers. I could pass the reference on with each prepareForSegue:sender: but this makes the whole view controller hierarchy dependent of the controllers. Also, I could use the singleton pattern but I'm not really a big fan of it.
What are my options, if I want the controllers loosely coupled? I've heard of Objection, and I'll be looking into that, but any input would be very welcome
I know this is a bit late but hopefully it can help others.
I solved this problem using protocols and checking the object to be injected responds to certain selectors.
In the prepareForSegue method I do one of two things:
id object = segue.destinationController;
if([object conformsToProtocol:#protocol(HasApplicationManager) ]){
[(id<HasApplicationManager>)object setApplicationManager:_applicationManager];
}
if([object respondsToSelector:#selector(setViewDelegate:)]){
[object performSelector:#selector(setViewDelegate:)withObject:self];
}
The first bit checks if the destination controller conforms to a specified protocol, this is still loosely coupled because you build your application with the composition pattern.
And secondly i check for a selector, this is more informal than protocols and probably more coupled and presents more problems. But it is a way of getting around having hundreds of 'IHave...' protocols.

The Proper Way to Store and Access Objects in Memory on the iPhone

I'm new to programming in iOS and I'm trying to figure out what the widely accepted "proper" way to store objects in memory is?
In my program I have a couple view controllers in a navigation controller and then on the lowermost view I have a modal view controller.
I have a class of object that I archive in a file and unarchive when I need to change the objects member variables. I need to be able to access and change these objects that I have archived from all of my view controllers.
Is the proper way to do this by unarchiving and then archiving the data in each view controller or is there a better way?
Multiple view controllers (that is classes deriving from UIViewController) is really frowned upon. A view controller should control the screen (or in rare cases such as the iPad split view, there can be two). If you need multiple classes to manage different subviews, thats fine, just don't inherit from UIViewController.
Depending on your application, you can keep your data in:
A singleton
In the application delegate (somewhat frowned upon)
As an object passed amongst the view controllers in your navigation hierarchy (makes sense in a document or file based application)

How to pass data between different UIViewControllers?

What is the best way to pass data from one view controller to another?
Suppose I push another view controller onto the present view controller. If I have to give some data to the view being pushed from the present view controller how do I do it?
Also how do I pass data from the pushed view to the earlier view?
So far I have done this by declaring functions in each controller and calling them. I find it dirty and want a cleaner way to do this. I don't want to use plists or sqlite as the data isn't that significant.
Keeping the data in AppDelegate is not a good idea if the amount of data is quite large since the data will live throughout the application lifecycle.
Why not call the setter(s) of the newly created UIViewController object to pass the data so that you can release it if the view goes offscreen or gets deallocated.
Why can,t you try making the variable in AppDelegate.Give that data to the variable of the AppDelegate and fetch it wherever you want in your application or UIViewControllers you will get that data.That value will be assigned to the the variable of the app delegate upto the termination of the application.
Try taking help from already asked several times Pass Data Between Several Viewcontrollers in a App.
Hope you get my point .....Good luck!

Resources