Monday, March 7, 2011

Objective-C [NSNotification] [Key-Value Observing]

The first thing developers have in mind when they start architecting their code is the ability to message other classes/objects no matter where the objects located in the structure. In singleton mode, we can find our ways/path to call that particular method by using dot syntax. For example, we use delegate as a singleton global class to access all the methods and properties in our app.

If you want to know what is an application delegate, I have covered the tip of the iceberg about app delegate here.
 
[[[UIApplication sharedApplication] someOtherClass] methods];

But there are problems associated with this type of chain dot-syntax to call a particular method, by using singleton in all of your messaging mechanism. You are actually digging your app's own grave if things turn out not in your favour. For example, there are semantic bugs that needed some reformation at the core of your application code, you need to take out some objects/classes and have to add on some other objects/classes. You might wonder, what's the problem then? I just remove the classes that are no longer needed, and just add in new ones. The problem lies in which you need to double check your singleton globals, in this case, your application delegate, and make sure those method calls that are no longer working, to be removed. And to also double check those delegate method calls from other viewcontrollers classes/objects to stop calling a method that will no longer exists in your application delegate. And that can be quite a lot of work considering some of your methods are tightly coupled with the others. In the end, you might left with one bad solution, that is to leave fathom methods that no longer do anything/do something else/commenting out those parts that you don't need anymore.

And that's exactly we don't dream of ourselves doing those tedious work tracing back where you were and erasing your footprints. When I was developing in Actionscript 3.0, I still am! I use eventdispatcher to bubble all of my events up the chains, and add the necessary number of eventlisteners to capture those events. It made my code loose coupled and I don't have to worry about events not being captured or not in the line of the chain when I moved things around or add things up. It just makes life much easier than the then:
 
MovieClip(root).parent.parent.methods();

And after a while, I discover pureMVC, that introduces a whole another new way of doing things. Not unique, but a seemingly easier way to message around. But that's for other time.

Alright, so what do have we here in Cocoa that we can use to facilitate our messaging/function calling?
Fortunately, we were given not one, but two types of notification-based messaging on top of conventional method calling/messaging. Something like eventdispatching in Actionscript 3.0, but not quite likely. As you see, eventdispatching works in such a way that the event bubbles through the chain bottoms up. But notification-based messaging, everyone in the application can use this method:
 
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(somethingMethod:)
name:kSomeNotif
object:someObject];

to observe/listen to the notifications that they are interested in, that are posted by other classes/objects that use this method:
 
[[NSNotificationCenter defaultCenter] postNotificationName:kSomeNotif
object:self
userInfo:someInfo];

Can you believe it? It's just that simple. You can choose whatever method you want to react to this notification and use the object that is passed alongside with it!
The other method, is called Key-Value Observing.

It's almost the same as NSNotification, but there are some differences. Let's look at how it's implemented in a typical objective-c environment.
 
[self addObserver:self
forKeyPath:@"string"
options:0
context:NULL];

The block of code above, just showed you how to add observer to a certain string event/change. This blocks only tells the viewcontroller to add itself as an observer, but there are more code to implement to conform to the protocol of KVO, which is
 
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (keyPath == @"string") {
[someLabel setText:string];
}
}

And there we go, we have just implement the method that is required by NSKeyValueObserving protocol. You may notice that the setText message is not using the object from the method but a dummy string that I have instantiated elsewhere. But you may use the object instead, if you have certain value that changes that you want to propagate to this class/object.

With the convenience these frameworks bring to our daily developer life, it comes with some cost. I will cover those area in the latter post where I have more time.

No comments:

Post a Comment