Understanding the MVC design pattern in Cocoa Touch - iphone

Usually I just put together an app in any random way, as long as it works, but this means I don't pay any attention to any design patterns. My application currently makes extensive use of global variables (I carry an instance of my AppDelegate in every view controller to access properties I declared in my AppDelegate.h). Although it does what I want it to do, I've read this is not a good design practice.
So I want to start making my code "legit". However, I can't imagine my app right now without global variables. They are so important to the well-being of the app, but this must mean I'm doing something wrong, right? I just can't imagine how else I'd do some things. Take for example this:
You have two view controllers here, a SideViewController and a MainViewController. Using global variables, such as say if the entire application had one shared instance of SideViewController and MainViewController (appDelegate.sideViewController and appDelegate.mainViewController), I can easily communicate between the two view controllers, so that if I press "News Feed" in my SideViewController, I can tell my MainViewController to reload it's view.
I can't imagine, however, how this would be done if these were not global variables? If an event occurs in my SideViewController, how would I notify my MainViewController, in a way that is in accordance with design standards?

I can't imagine, however, how this would be done if these were not
global variables? If an event occurs in my SideViewController, how
would I notify my MainViewController, in a way that is in accordance
with design standards?
The same way you do it now, except that the SideViewController gets its reference to the MainViewController from a different place.
How are these two view controllers created? It's likely that it happens in one of two ways:
One of the objects creates the other. In this case, maybe the MainViewController creates the SideViewController.
Some other object, such as the app delegate or another view controller, creates them both.
In the first case, the MainViewController has a reference to the SideViewController as soon as it creates it. It can store that reference in one of its own instance variables, so that it can always send messages to the SideViewController that it created. Similarly, the MainViewController can give the SideViewController a reference to itself (that is, to the MainViewController), and the SideViewController can store that and use it in the future to talk to its MainViewController.
The second case is similar -- if the app delegate (or some other object) creates both MainViewController and SideViewController, that object knows about both objects and can configure each with a reference to the other.
In both cases, the objects in question are able to communicate with each other just as easily as they ever did and there's no need for a global variable.
What I've explained above is perhaps the simplest way to accomplish what you asked for -- communication between two objects. There are a number of patterns that can be used to refine the relationship between those objects to make your code even better:
delegation: Give SideViewController a delegate property, and define some protocol that establishes what SideViewController expects of its delegate. Implement that protocol in MainViewController. Make your MainViewController instance the SideViewController's delegate. SideViewController doesn't need to know exactly what type its delegate is -- it only cares that it's delegate implements the required protocol. This makes it easy to use SideViewController with something other than MainViewController if that opportunity arises, or to use it in a different project.
notifications: SideViewController may not even need a delegate -- it can simply broadcast notifications about certain events to any object that happens to be listening. This is particularly effective if more than one object might need to know about something that happens in SideViewController, or if the objects that care about SideViewController's actions might change.
MVC: Instead of telling MainViewController that something has changed, SideViewController just changes the data in the model. Whenever the MainViewController's view appears (or any other view controller's view, for that matter), the controller reads the data from the model and redisplays itself.
If you're interested, you might want to pick up a copy of Erik Buck's Cocoa Design Patterns, which explains these patterns and many others in great detail. Don't feel like you have to learn it all at once, or that it's all too much trouble. Learn a little bit at a time and see how it improves (or doesn't) your projects.

Related

Is setting a pointer from a singleton to a viewController and updating GUI a violation of MVC

I'd like to ask a theoretical question pertaining to good code practice and the MVC model, Here is the case:
The design contains a RootViewController and a singleton class. The singleton acts as a controller with a timer objects that should be available throughout the app. The timer object consists of a UISwitch and an NSTimer, they are both owned by the singleton controller so the UISwitch can be added to new viewControllers on demand and the timer object is accessible throughout the app.
In order to update the RootViewController's screen with the current timer's count i created a pointer in the singleton to the RootViewController and have the RootViewController set itself to that pointer, similar to [singeltonOBject setDelegate:self].
Using this design the UILabel of the RootViewController can be accessed and updated from the singleton when the timer ticks. I chose to do that because i didn't have time to implement a regular delegate.
Note that the RootViewController is owned by the AppDelegate and the the singleton class is obviously NOT owned by the RootViewController. Therefore there is no retain cycle.
Question:
Is the setting of a pointer from the singleton to the RootViewController and updating the UILable from the singleton controller a violation of good coding practice, are there any basic principles that are not fulfilled?
Thanks for your answer!
Problem
Generally when something doesn't feel quite right, thats because it's not.
While your code will work it is not going to be easy to maintain in the future and is liable to breaking. Even if you never plan on looking at this code again, it is always good to practice good coding conventions.
I recommend reading The Pragmatic Programmer which contains lots of tips for programmers on how to write better code. One of those tips is Minimize Coupling Between Modules. Right now your RootViewController knows about your Singleton and your Singleton knows about your RootViewController so they are both coupled to each other. In the future, when you change one you are likely to have to change the other one as well.
What if you want to add another label?
You will have to add the label in the RootViewController and then change your singleton to update that label as well.
What if you remove the label altogether? Lets say you go back to this in a years time and remove the label, suddenly there is another class that is not compiling and you might not remember why. You have broken code in a completely separate part of your application.
As for following MVC, this is in violation of that. Your view is being modified by something separate. If MVC is setup correctly you should be able to put on as many views as you want without having to change any code that is controlling data, in this case your timer.
Now as for memory management, your RootViewController is now being retained by this Singleton. Singleton's exist for the entire life of an application. You are right that you do not technically have a retain cycle however your RootViewController will now never be deallocated. In most applications this does not matter as the RootViewController always remains at the bottom of the stack but it is a coincidence and thus cannot be reliably programmed on. This is actually another tip from The Pragmatic Programmer, Don’t Program by Coincidence.
Solution
A better solution would be to use a notifications if you really need a global timer like you say (another story is that your global timer singleton does not sound like a good idea). Whenever you were updating your label from within your singleton you can fire a notification instead. Your RootViewController will receive this notification and can update its label. You can pass data in a notification if needs be. Now in the future if you make a change to the view and want to update something else you only need to change code in one location (The RootViewController).

Passing NSString from one ViewController to other's VC NSMutableArray

I'm a starting iOS developer and I would like to get the idea of NSMutableArray.
Specifically, I want to pass NSString value from one VC to NSMutableArray, belonging to another view controller. I also want that NSMutableArray to populate UITableView on its view. Any ideas how to do this?
For example, I have this action that the user triggers from within 1st view
- (IBAction)addToFav:(id)sender {
}
And I want to pass a value of NSString myBookString to the NSMutableArray array in the 2nd view.
The task is fairly simple, but I can't quite understand why you can't pass the values to NSMutableArray outside this - (void)insertObject:(id)anObject atIndex:(NSUInteger)index method mentioned in Apple's reference docs.
Thanks in advance!
EDIT: My views are different VC belonging to UITabBar and to UINavigationController at the same time
You need a communication between two controllers. There are several solutions. Pick one of the following. I recommend delegate.
From http://www.hollance.com/
When you have two objects A and B, say two view controllers, that you want to make talk to each other, you can choose from the following options:
NSNotificationCenter.
This is anonymous one-to-many communication. Object A posts a notification to the NSNotificationCenter, which then distributes it to any other objects listening for that notification, including Object B. A and B do not have to know anything about each other, so this is a very loose coupling. Maybe a little too loose…
KVO (Key-Value Observing).
One object observes the properties of another. This is a very tight
coupling, because Object B is now peeking directly into Object A. The
advantage of KVO is that Object A doesn’t have to be aware of this at
all, and therefore does not need to send out any notifications — the
KVO mechanism takes care of this behind the scenes.
Direct pointers.
Object A has a pointer to Object B and directly sends it messages
when something of interest happens. This is the tightest coupling
possible because A and B cannot function without each other. In the
case of view controllers you generally want to avoid this.
Delegates
Object B is a delegate of Object A. In this scenario, Object A does
not know anything about Object B. It just knows that some object
performs the role of its delegate and it will happily send messages
to that delegate, but it doesn’t know — or care — that this is Object
B. The delegate pattern is often the preferred way to communicate
between view controllers, but it takes some work to set up.
Blocks.
Essentially the same approach as delegates, except that Object B now
gives Object A one or more blocks (closures) to be executed when
certain events take place. There is no formal delegate protocol and
the only thing that Object A sees of Object B is the blocks it is
given.
NSMutableArray is just that, a standard mutable array implementation. It has all of the functionality you would expect from one in any other language/framework. docs.
What is the problem with the way adding elements to an array works? You can also just do [array addObject:object] if you don't mind adding it to the tail.
To answer the rest of your question, there are many ways to transfer data from one controller to another. How is your navigation set up? Are you using a UITabBarController, or a UINavigationController? How are the views related to each other? If they are nested, you can pass data directly from one to another. If not, you could use something like your app delegate to hold the data and pass it around.

Need of Delegation in iPhone Development or Objective C

What is the need of delegation in iphone/ipad development or objective C?
I read so many articles on it. All were telling how to implement the concept, but no one was telling why we need to implement that, in which case we should implement it.
Suppose you want to implement Login functionality in your app ... now you won't show Login screen every time you run your app.. only when it is first started and you don't have a login and password...
So in this case..
Your app starts :
View 1 loads (default view )
You check no Login name is there..
You load a new view..(Login View ) .
User enter his details..you get your login and password...
now you want to go back to default view and load the main app with
the names the user entered in Login View....
Now you will use delegate to pass these information(login details) back to default View..so that it knows..its details. now there are many different ways to do these things...like notification and singleton classes.. but when you want to sent more than 3-4 sets of data.. it is best to use delegates
Think of all the components that iOS and Cocoa provide you with. TableViews, TextFields, PopOvers...etc.
When the developers wrote these components, they couldn't possibly know all the various implementations that us developers were going to create using these components. But we need somehow to communicate with them in a generic way.
These components use delegates. The delegate is an implementation independent way of describing some behaviour that your component can conform to.
When UITableView need to find out what is the height of the rows, the UITableView only needs to know about UITableViewDelegate. It doesn't need to know about MyTableViewController, JohnsTableViewController, BobsTableViewController... etc.
So the delegate is decoupling the component from the implementation and the type.
Decoupling is a good thing. It makes maintaing and changing code a lot easier, and makes code reusable.
Delegation is a simple and powerful pattern in which one object in a
program acts on behalf of, or in coordination with, another object.
The delegating object keeps a reference to the other object—the
delegate—and at the appropriate time sends a message to it. The
message informs the delegate of an event that the delegating object is
about to handle or has just handled. The delegate may respond to the
message by updating the appearance or state of itself or other objects
in the application, and in some cases it can return a value that
affects how an impending event is handled. The main value of
delegation is that it allows you to easily customize the behavior of
several objects in one central object.
SOURCE
Use a delegate if you want to talk to only one object. For example, a
tableView has a delegate - only one object should be responsible for
dealing with it.
Use notifications if you want to tell everyone that something has
happened. For example in low memory situations a notification is sent
telling your app that there has been a memory warning. Because lots of
objects in your app might want to lower their memory usage it's a
notification.
this was an answer posted to my question here
There are two key benefits of delegation: customizing objects without subclassing, and improving encapsulation.
Customization without subclassing is a benefit you get from many of the Cocoa and Cocoa-Touch APIs using the delegate pattern. If they didn't do so, you might have to subclass a UITableView every time you wanted to change its behavior by using different types of cells or a different data source. Instead, you just set the table view's delegate and data source to customize its behavior.
As for encapsulation, the delegate pattern helps you keep the different components of your code separate. For example, if your custom View needs to have some data, it would be bad practice to simply give it access to your Model, or even full access to your Controller. Instead, you'd probably set up some kind of delegate protocol for your View that your Controller would implement. That way your classes know no more about each other than they need to, so that changes in one part would be less likely to break others.

Can someone please explain delegates in objective-c?

I have been using Objective-C for a while and pretty much understand most of its features. However, the concept of delegates eludes me. Can someone please give a succinct and easy to comprehend explanation of what delegates are, how they are used in the iPhone SDK, and how I can best make use of them in my own code?
Thank you!
There are a couple main reasons to use delegates in Objective-C, which are subtly different:
Enhancing the base functionality of a framework class. For example, a UITableView is pretty boring on its own, so you can give it a delegate to handle the interesting bits (creating table cells, adding text to section headers, what have you). This way, UITableView never changes, but different table views can look and act very differently.
Communicating to parent objects in your dependency hierarchy. For example, you may have a view with a button that the user may push to do something that affects other views. The view will have to send a message to its parent view, or perhaps the view controller, so that it can create or destroy or modify other views. To do this you'd pass the parent object into your view, most likely through a protocol, as a weak reference (in Objective-C, an assign property). The view could then send any message declared in the protocol to the parent, or delegate, object.
This approach need not involve views. For example NSURLConnection passes event back to its delegate, which may be the object that created it, using this mechanism.
Essentially, all a delegate is, is an object that accepts feedback from another object. Put simply, when stuff happens to an object, it tells its delegate (assuming it has one).
For instance, lets say I have a UIViewController with a UITextView placed in the middle of the view. I set up my UIViewController to be the delegate of the UITextView. Then, when certain actions are performed on the text view (begin editing, text changes, end editing, etc), it tells it's delegate so it can do whatever logic it needs to do, like spell checking every time characters change, or dismissing the keyboard when it receives a return key press.
Delegate methods perform a similar function to callback functions in C.
Hope that makes sense :)
Best and simple concept I got from a Lynda.com Tutorial was: When you set a Delegate it means you have been given work to do. So, if you want to use methods that are written in a protocol method, you must implement them by searching in the Delegate Class Reference and using them. I hope it helped.
By the way, Delegates are excellents. They are your friends. They have been made to make your life as a programmer much easier.

Having Freudian child parent problems with my objects. Need some pointers and/or Reference?

I think I have a basic question that is sort of hard to look up, I think.
Objective-C for Iphone.
I want to create two view controller instances that message and update an instance of a Model Class. How do you do this? I would prefer no using singletons. It's basically an "I really want to learn from you guys because this is awesome and I want to be awesome too!" question.
I would prefer we keep app delegate, singletons, nsnotification center out of the picture. App delegate specifically in that I dont think I wnat to have my data object created by app delegate, but I may have to.
The way, as I understand it, this works is sort of like this. Navigation Controller creates instance of FirstLevelViewController. My FirstLevelViewController creates instances of my SecondLevelViewControllers and then when told to pushes them onto the navcontroller stack.
I have my Model Instance being created by my firstlevelviewcontroller instance. Is that wrong? I think I need a reference to the instance passed to my secondlevelviewcontroller, but I'm having trouble because I can't figure out what the instance name of the firstlevelviewcontroller is (I think NavController instantiated it).
Help is so very much appreciated.
Assuming the model stays the same object (it can be mutable but not deallocated within the lifetime of BOTH view controllers), one might use a separate variable in each view controller to point to the same model class, with each view controller not knowing about the other. This is of course dependent on your application specific logic -- if one view controller 'knows about' the other than of course it makes sense to have the model be 'owned' but the independent one, and accessible to the dependent one via properties. However this considered bad because it promotes code coupling and dependency, which is looked at as poor coding. As to how both view controllers get the same model instance, typically it would be set (preferably in initialization) by whatever knows about them both, such as a higher level view controller, or if they are root view controllers, the app delegate.