Avoiding coupling in a document-based Cocoa app? - objective-c

I'm new to Mac programming and I'm working on a document-based application.
My NSDocument subclass creates a NSWindowController subclass. This window controller creates two NSViewController subclasses as well.
Sometimes, a change in one of the views of a NSViewController needs to notify the NSDocument and/or the main model class. Also, a change in the model needs to be notified to every/some view(s).
My question is: what is the best approach so that there is no (or minimum) coupling? I know there are several choices, but I'm not sure which one suits best for my application as I'm newbie not to programming but to Cocoa and especially NSDocument:
KVO. Looks nice and easy to implement, but I don't like the idea of not explicitly notifying the observer(s) about a change (AFAIK, self.someProperty = newValue does automagically notify observers), and don't like the fact that you have to register to property names which could change in time.
Notifications. I know what they are and I've used them for iOS. But I've read somewhere that they are not guaranteed to be sent immediately to observers. Is it true? If not, do you see them as a good approach for a document-based app?
Delegates. Yes, under normal conditions (or what I've usually seen), a class has one delegate. But creating an array of delegates works as well (just tested it). The problem I see here is that every time I need to notify the delegates I have to loop through them, make sure they respond to a method, and call that method.
Are there any other alternatives I'm missing?

KVO by a controller class is the most common way to do coupling between a model and its view(s). In fact, Cocoa Bindings, which are intended to mostly eliminate code in the controller layer, are based on KVO. It is true that KVO/KVC relies on property names, and that if those change, you'll have to change the bindings or KVO setup connecting your view. However, it's not usually feasible to make your views completely unaware of the underlying model specifics, so I don't see this as a problem.
My recommendation would be to use Cocoa Binding where you can, as they eliminate a lot of glue code. In places where they can't be used, your controllers (the middle layer in MVC) should use KVO to observe model changes and update the appropriate views. Changes in the views can be passed back to the model via property accessors and/or KVC by the controllers.

Yes, under normal conditions (or what I've usually seen), a class has
one delegate. But creating an array of delegates works as well (just
tested it).
Delegates are often used to modify the behavior of the delegating object. An application delegate is a good example: NSApplication by itself isn't very interesting; it relies on its delegate to define the interesting behavior of the application. Having multiple delegates all trying to modify the behavior of a single object could be a problem if the various delegates conflict with each other. What do you do if the delegates disagree?
There are some cases in Cocoa where a class uses more than one delegate, but each one has a separate role. For example, NSTableView has both a delegate and a data source, but both are really delegates of a sort.
The problem I see here is that every time I need to notify the
delegates I have to loop through them, make sure they respond to a
method, and call that method.
That's not hard to solve. For example, you could create an NSInvocation to encapsulate the call, and then send the invocation to each "delegate." However, if you do that you'll have nearly reinvented the notification system. If you need the one-to-many communication that you'd get with your multiple delegates proposal, you'll probably be better off using notifications or KVO.

Related

confusion over Objective-c views, delegates, and outlets

I am trying to teach myself objective-c, but coming from a Python/Java background, it is proving very difficult. I tried to post a bunch of points I am confused on, but it was marked as too vague, so I'll break it into sections.
First, every example of a delegate and outlet I've found uses cocoa view code to get the idea across. Unfortunately, I don't yet understand enough of the code to grasp the example's point. So, can anyone provide a more basic example of a delegate? My understanding is that it is a way of subclassing; how is this better than traditional subclassing? Why does every cocoa project automatically include appDelegate.m? Can delegates be used for other purposes, not just GUI stuff?
Okay, I think I see. So a delegate is a class that conforms to the protocol of some other class. A protocol is simply a list of methods and variables that have to (or can, if set to optional) be implemented in the delegate class. To make a delegate, you have to use the #interface keyword, then the name of your delegate, then (in < > signs) the protocol name? So if class c1 wants to set itself up as a delegate of class c, class c must first specify a protocol, right? You would then be able to implement everything in c's protocol in c1:
#interface c1;
I feel like I'm missing some bits there, but hopefully I have the concepts right. :) This also explains the mysterious less- and greater-than signs; they declare what interface the delegate implements.
Outlets are similarly always tied to view code. They seem to be some kind of inter-object messaging system. Is that right? Again, an example of a basic outlet that is not mixed in with complex GUI statements would be great.
So outlets are never needed? I know that IBOutlet and IBAction are not needed except for use with Interface Builder, but I thought outlets were more general than that? The docs seemed to indicate that they are not even specifically for interfaces, but could be used for anything.
Thanks in advance for any help.
Update: Delegates don't have to conform to protocols. Protocols just make it easier to require some classes to have methods. It allows you to know for certain an object one has set as a delegate implements a certain method so you can call it safely, and allows the compiler to verify that method is indeed implemented (if you declare a delegate instance variable as id<SomeProtocol> delegate, the compiler will give a warning or error if you try to set delegate to an object of a class that doesn't conform to SomeProtocol.
Protocols help ensure safety, but they're not strictly necessary. A class can have a delegate (or multiple!), and they don't have to conform to any protocols at all.
As for outlets, no, they're specifically and only used with Interface Builder. The IBOutlet and IBAction keywords have no effect on code (they're even stripped out before compile time) - they're only markers for Interface Builder to look for so it knows which properties and methods should be accessible within the interface. The term 'outlet' is a direct reference to something marked as an IBOutlet, and is really not used in any other context that I can tell.
Again, it's okay if you don't understand this right away. Think it over a bit, and at some point, it'll just 'click'. I was caught up on delegates for a long time, just like this, before one day, I realized that delegates really aren't any special. They're regular objects referenced by other objects - it's just that this design pattern has a special name (delegation), and these objects are only called delegates. They could just as easily be called gyros or falafels, and the net effect would be the same. :P
You don't need to name an object delegate for it to be a delegate; it's just a convention.
About delegates: the first thing to understand, and this got me for a while until I had the proper "Aha!" moment, is that there is nothing special about a "delegate". The word "delegate" is just a title for a type of object that another class depends on, very often for content or decision-making. A developer will use a delegate when they don't want to (or can't) tie one of their classes to another class by name - it's an Object-Oriented way of decoupling and making classes more generic.
Now, very often, classes will require delegates to have specific methods they rely on, and one way to ensure that is with a protocol (more commonly known as an interface in Java). Protocols define a list of methods; classes "conform" to a protocol if they declare they do in their interface (e.g. #interface IFObject : NSObject <SomeProtocol> { ... }) and if they implement all the methods they're required to. Protocols can have optional methods as well.
This model is used often with view controllers, views, and the GUI in general because many AppKit and UIKit classes are written to be as generic as possible. NSTableView, for instance, implements the most basic behavior it can possibly implement without requiring any implementation-specific information; for the rest, it relies on other objects, ones that conform to the NSTableViewDelegate and NSTableViewDataSource protocols. Any object can conform to the protocols, as long as they implement the right methods (and in this case, a controller class will usually implement methods from both protocols, but it doesn't have to be so). In fact, one easy way to understand this topic better is to take a look at NSTableView - it's got a delegate property and a dataSource property, but in effect, they're no different. delegate could be called monkeyButt, and the concept would still work. The key is to not treat delegates as a black box - there's nothing special about them.
Delegates can be also used for non-GUI purposes; one concrete example, as you mention, is the app delegate. NSApplication sends a delegate notifications to let it know when the application has been launched (among other things), so it can set up shop. Again, any object can be a delegate to any other object, for any purpose. It's simply a convention.
Briefly about outlets: as others have mentioned, outlets are simply connections between an interface defined in an XIB and your code. They're a way of letting Xcode link up the interface to the appropriate elements so that when your application loads the interface file, it can load up the right pieces of code or execute them.
They're generally an easier way of setting up an interface - they're not strictly necessary (you can create an interface programmatically, without using an XIB file), but if you do decide to go the XIB route, they're how you relate your interface to your code.
A delegate is an object that is delegated some task by an object it declares itself the delegate of. Let's say an object does some task and then needs to notify the object that "owns" it, so to speak. In order to allow the object to work under any conditions, it cannot be allowed to know what type of object it should contact, so we set its delegate and adhere to its protocol. Setting the object's delegate is like saying "Here's the object I want you to use contact with the messages declared in your protocol. I promise the object actually implements the methods in the protocol." For example, you might see this.
#protocol SpriteDelegateProtocol
#required
- (void) projectionMatrix;
#optional
- (void) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
#end
#interface Sprite
#property (nonatomic, assign) id<SpriteDelegateProtocol> delegate;
#end
The interface for our sprite object declares that it has a property called a delegate, which is of type id. It can be any object, but it must adhere to the protocol in the triangle brackets. If it says it adheres to the protocol, it has to implement the methods declared under the #required and can implement the ones listed under the #optional. It's up to us to determine whether or not our delegate actually implements the optional methods using something like respondsToSelector:. We might even store the return value if we had a lot of methods to do that for.
The application delegate is special in that it is the delegate to our UIApplication object. It receives messages on application state, such as applicationDidEnterBackground:. You can see what methods are in the protocol adhered to by our application delegate here.
Delegates can be used with any object. Any object can say it has a delegate property to set, and that it must have the following methods as shown above. The protocol is essentially a portable interface that can be used to tell another object what we need it to implement so that we can call said methods to delegate some portion of functionality out to it. We can notify our delegate when a task has completed, ask it to give us information (typically called a data source instead of a delegate so that they can be different objects if you want) or ask it whether or not we should do some task at all.
An outlet is a way of connecting a view instantiated in a NIB or storyboard to a property in its controller. So, if you place a UIViewController into your main storyboard and change its class to MyGreatControllerSubclass then proceed to place a button in that controller's view, you might want to hook that button up to an "outlet" (property) in the controller's interface so that you can access the button from the controller later.
No delegates are not a way of subclassing. I also came from Java and have been doing O-C for almost 5 years now.
Delegates generally conform to Protocols, which are the equivalent of Interfaces. What's great about that is it leaves you a lot of flexibility in how you implement the things that are covered by the delegate. So for instance, you will see that Table Views can be implemented by extending UITableViewController or implementing the delegate. That way, if you have a composed view where a user is selecting items from one table and putting them into another, you can do a single controller and have it perform the delegation for both views.
The best way to think about delegates is as examples of message/event oriented callbacks. Have you ever heard the saying that what makes a Framework different from ordinary programming is, with a Framework, it tells you what it wants you to do to ensure the results you seek? That is what delegation is. I was doing a Collection View last night and could not get the edit menu to come up. Just provide delegation of three methods, know nothing about how the menu is invoked, where the Long Press gesture handler is, etc.
Note that Delegates are the glue that makes Dependency Injection unneeded in the O-C world. I prefer them.
Delegates are the common design pattern (http://en.wikipedia.org/wiki/Delegation_pattern), they are not objective-c specific.
Outlets make possibly the binding of Controller and View (GUI). May be you know the MVC paradigm (model-view-controller)? So you build your GUI (the View from MVC) with Interface Builder and bind the elements of this GUI such as Buttons, Text fields and so on to your Obj-C code (the Controller from MVC) using outlets.
Take a look at this post: Conforming Objective-C’s Protocols in C# Codes
Don't worry about the word "C#" in the title, you could just ignore that part. The main part of this post talks about protocols and delegates in Objective-C. This might be helpful.

Can two objects be delegates of each other...?

Is it ok to have two objects as delgates of each other..? My scenario is that I have a view which is shown in two modes.. first: Create mode and second: Edit mode
In Create Mode all the fields are empty and I take data from the view which is filled in by the user and I update my data model.
And In View Mode I fill up the view from my data model.
This is being done using a spilt view controller(because of this I am forced to use delegation). I wish I could explain this better but this is the best I can do. As of now I am using delegation to communicate from A to B and Notification from B to A.
Would this work fine if I use delegation in both ways... or are there any complexities involved which I can't foresee?
There are a few problems that could occur, but if you take the necessary precautions, it will be fine:
Ensure both delegates are weak referenced. This means using #property (weak) on ARC or #property (assign). This will prevent retain cycles from occurring.
Ensure you don't get into a situation where a delegate method calls the delegate method of the other controller, which calls the same delegate method in the first controller and so on. You could easily get an infinite loop if you are not careful.
A discussion or debate on whether or not this is the best design pattern in this situation is not really something that belongs on SO. But doing it this way is possible if you are careful, which is the answer to your question.

When to use NSNotificationCenter

I want to have multiple observers on multiple events of a single object (1-to-N relationship).
A mechanism to achieve this task is provided by the NSNotificationCenter. The mechanism looks pretty overkill when used for my problem.
How I would do it manually without the use of NSNotificationCenter:
- (void)addDelegate:(id<DelegateProtocol>)delegate;
- (void)removeDelegate:(id<DelegateProtocol>)delegate;
to add and remove observers from my object.
- (void)someEventFired:(NSObject<NSCopying> *)eventData
{
for (id delegate in delegates) {
NSObject *data = [eventData copy];
[delegate someEventFired:data];
}
}
This mechanism is straight-forward and simple to implement without the objects having to share additional strings.
Is there an official pattern for 1-to-N delegates (like C# events) in an iOS framework besides the NSNotificationCenter?
When should the NSNotificationCenter be used and when not?
When should an implementation like the one I am suggesting here be used and when not?
By convention, delegates should probably only be used for 1:1 relationships. If you really need 1:N relationships for this type of functionality, you have two options:
As you mentioned, NSNotificationCenter.
Key-Value Observing (also known as KVO).
KVO is appropriate if you only care about when a particular property of an object changes. Otherwise, you should really just consider using NSNotificationCenter. You can even be notified only when a specific object posts that notification by passing that object into the addObserver:selector:name:object: method.
Apple uses NSNotification in similar scenarios (like the notifications defined for UITextField, including UITextFieldTextDidBeginEditingNotification, UITextFieldTextDidChangeNotification, and UITextFieldTextDidEndEditingNotification).
using notifications is broadcasting: 1 sender just sends an information and who ever tuned in, receives it. Petty much like a radio station, there is no channel back (lets for the moment forget about telephones)
delegation is something different. Th object, that asks a deleagte to do something, usually needs a result of that request, there fore delegation is a 1-to-1 communication, that is always initiated by the object, not the delegate (while the object can have methods that can be called to inform the object to initiate the communication, ie [tableView reloadData]).
So if the sender needs to get data back, it is delegation. If the sender doesn't care about anything after broadcasting, go with notifications.
If you run into the situation, that you need delegation, but several objects should implement the protocol. you should have 1 delegate, that hold references to the other objects and calls the methods on the senders behalf — or you could go with blocks.
NSNotificationCenter is not overkill for what you are suggesting, it is exactly the right solution. It prevents the observed object having to know or care about its observers, making your code more loosely coupled and cleaner.
Sharing strings for notification names is trivial and they can be defined in either a shared constants file or in the header of the observed object, if your observers need to import this header to do their jobs.
Your proposed solution is neither simpler than using NSNotificationCenter nor is it thread safe.
To make your solution thread safe, you would need to provide a mechanism to prevent the delegates array from changing while the event dispatch for loop is running.
Your solution also requires that you maintain the delegates array in your class. With the NotificationCenter you can simply use the default center and you don't need to implement the add/remove methods in your class. Instead, instances can register themselves to receive notifications as they see best fit (selector/block, queue, source). Your source class doesn't have to worry about those details. It only needs to register itself as a source of notifications of a specified type. Using blocks to handle notifications is really convenient.
An alternative to the notification center is to use Key-Value-Observing if that meets the needs of your use case.
Ultimately, the mechanism you decide to use depends on how best it applies to your specific use case.
A 1-to-N delegate relationship doesn't make sense. Have a look at
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
for example. What if this object really had n delegates? How should it decide which of the n views it gets back from all its delegates should be used? Delegates are exactly this 1-to-1 principle.
The NSNotificationCenter is the right approach. Simply use
addObserver:selector:name:object:
respectively
postNotification:
This is definitely not too much code. And it's very easy for you as the center handles all calls.
You don't want to use NSNotificationCenter for anything other than system-wide events (e.g. the appearance of the keyboard or some similar event). The reason is that it is completely not type-safe, can make everything dependent on everything and that you get no compile time checks or usage search results anymore.
KVO in my opinion should not be used to observe changes outside of the object you're listening to since it has similar down sides (no compile time checks, crashes if you don't remove listeners properly or register them twice).
The addDelegate/removeDelegate pattern that you pose is completely the right path in my opinion since that has the advantage of maintaining type-safety and compiler checks and makes dependencies explicit. The only problem is that Apple doesn't supply an out-of-the-box solution for this pattern, since you need a collection type that weakly retains its elements to avoid retain cycles.
However, see code from my BMCommons framework which solves this problem neatly using BMNullableArray and macros. See the BMCore.h header for a definition of those macros:
BM_LISTENER_METHOD_DECLARATION(protocol)
BM_LISTENER_METHOD_IMPLEMENTATION(protocol)
The implementation ensures that the same listener will never be added twice and also that listeners are weakly retained, not causing any crash even if they forget to deregister themselves upon deallocation (although I prefer to catch this condition with an assert since it is a programming mistake).
I say NSNotificationCenter should ALWAYS be used, over the delegate model, except in situations where you query a delegate on information (e.g. -webView:shouldLoadRequest:). It is more stable, easier to implement, and results in cleaner code then trying to use a delegate. The other alternative is blocks, which can be good, but they can be a pain when it comes to memory-managment.
In the end, it's up to you, but I think that NSNotificationCenter is the best way to go in almost any situation, if only for the multiple observer functionality.

Design of notifying about model changes in iOS game

I'm developing a rogue like game (iOS/Cocos2d). I have a object of class Map, which has bunch of GameObjects.
I have GameViewController class. When something in model happens (creature killed, player moved, anything), I need to notify GameViewController about this changes. How to do that?
I see two options:
GameViewController instance could be a delegate of Map and a delegate of every GameObject.
GameViewController will listen NSNotifications from Map and GameObjects.
Which way is better? Why?
Cocos is a strongly singleton-based library, so the singleton method is quite common in Cocos games. That does not mean, however, it is the logical default choice.
Your second option is generally a wiser and safer approach for any program, not just Cocos. NSNotifications allow you to notify objects from other objects without getting into a potentially buggy state of passing numerous references or singletons around in your program. If you can achieve your goals with a few notifications, this is the way to go.
If you find you are using NSNotifications to an extreme degree, like multiple notifications every second, then you should consider either passing references around between your objects via pointers, or creating your parent class or main Cocos scene class as a singleton.
Just remember that when you get singletons involved, though they are easy to implement, it is just as easy to abuse them. You don't want to get into the habit of having children classes control the behavior of their siblings just because they can access the parent and the parent's methods easily.

Objective-C Cocoa Touch: Delegates - I almost get it. Last steps

OK I alllmost get it. I've done a bunch of reading in objective-c and I really want to understand delegation because it seems super important for cocoa-touch and I want to design an iPhone app.
So, a delegate is an object that can be given a certain task. It is said to follow a 'protocol' if it implements certain functions. So a view-controller, for example, can say "hey, I'm not sure where to get this data from..or hey, I'm not sure how to format this thing...can you do it for me?" and the delegate is like "sure I got you covered".
OK that makes sense to me. What doesn't make sense to me is how I get the delegate to return stuff to a view controller. Like say my delegate can go to a URL and read a sports score or something. So I say "delegate get me this score" ...how do I get the view controller to say "got it, here it is" and then have it inside the view controller. There might be a gap in my understanding here. Would I have to instantiate the view controller inside the delegate? That doesn't make sense to me...because then I'd have two view controllers...Feel free to change my analogy if you can make it clearer.
Thanks!
I think you're confused because a similar pattern is used for (but is not limited to!) two common tasks, both of which apply to your situation.
The patterns
Having an external object provide data for you (this is usually called a data source). See, for example, the UITableViewDataSource protocol.
This is implemented by a return value from the method: such as - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
The object implementing the protocol returns some value (in this case, a cell) to the caller.
The thing I'll mention about data sources: the data source itself (the object implementing the protocol) usually contains more of your application's custom logic, while the controller which requires a data source can be more generic. For example, UITableView is a generic view controller that displays a table view, while a class implementing the UITableViewDataSource protocol needs to know the details of your application's database.
(However, to be thorough, you do often subclass UITableView for custom logic, but this is most often presentation logic and not business logic.)
These methods call in to your application logic, and are expected to return immediately.
Providing callbacks once you've finished loading data.
For example, the NSURLConnection class has the corresponding NSURLConnectionDelegate protocol. The most common use pattern is:
Your object creates a NSURLConnection, with itself as the delegate.
You configure and start the connection.
You receive progress and data via the delegate methods you implement.
In this case the object which requires a delegate is an auxiliary object that knows how to load data from a URL in the background. The delegate methods are callbacks to your application logic, and are called at any time after the object is told to start loading data (or whatever it's designed to do).
Delegation is also used for other things on iOS, such as the UI-related tasks performed by objects conforming to UITableViewDelegate.
Your situation
This all depends on what your application is, and what your view controller is responsible for — but it sounds like you want the view controller to delegate the loading of data — basically, it needs a data source. (You should also consider if the built-in UITableView & UITableViewDataSource might suit your needs.) But if your data source is going to asynchronously load data from the internet, it might need to implement some data-loading callbacks via something such as NSURLConnection.
These two methods don't necessarily go together well, because the view controller will expect its data source to immediately return data, but the data source might need to wait for data to load.
This is why UITableView has a method -reloadData, so the object which serves as the data source can tell it when data is available. You might want to use a pattern like this in your application.
(But again, in all likelihood you won't need to implement a fully custom stack — either you can combine some classes to reduce your use of delegation, or you can use more built-in classes to suit your needs.)
Define your protocol's methods with return values.
That said, getting a URL is a bad example, since waiting for a delegate to return the results would block the calling thread. In this case, you would have to have a way for the delegate to call back with the results when done. This can be achieved either by passing a delegate to the delegate, or passing one or more Objective-C blocks to the delegate (onSuccess, onError, …).
On that subject, blocks are much easier to code than delegates and protocols, and are gradually supplanting them in Apple's and third-party APIs.