Garbage Collection and KVO and NSNotificationCenter, Oh My!

Recently, I ran into some problems with data dependencies and garbage collection in my bespoke model classes. Several classes in my model code register as observers of other model classes using either KVO or via NSNotificationCenter.

Although I’m using garbage collection, I was trying to be a good boy by implementing a dispose method on some of these model classes so that they could de-register as observers when they were no longer an active participant of the model.

The problem with this approach is that various Cocoa classes, such as NSUndoManager, don’t easily offer me the opportunity to invoke my dispose method (say for example when the redo queue is cleared by registering a new invocation). There are a few different solutions to the problem. In my case, registering the “activation” and “deactivation” of my model classes (i.e. the adding and removing of themselves as observers) with the NSUndoManager is the one I opted for.

In the course of implementing this code, I played around with using NSObject's finalize method as a way to de-register my observers, rather than inducing the undo manager to invoke my own dispose method. Generally speaking, I try to stay away from finalize methods in garbage collected languages, and Objective-C is no exception. Apple cautions against the madness of using finalize methods for performing any serious work.

All that said, it got me thinking about where exactly Apple expects objects to de-register their KVO and NSNotificationCenter observers in the general case. The problem with remove observers in finalize methods are several:

  1. You are forced to introduce a finalize method where you otherwise wouldn’t have to. Not good for performance and can open up a Pandora’s box of non-determinism.
  2. The finalizer’s of objects collected in the same cycle are not guaranteed to run in any particular order. So de-registering object A as an observer of object B in object A’s finalize method might happen after object B is already collected (i.e. when it’s invalid), leading to “Cannot remove an observer … for the key path … from … because it is not registered as an observer.”
  3. The de-registration of observers happens at a non-deterministic time (i.e. whenever the garbage collector gets around to running).

As far as items #1 and #2 are concerned, there is a better way, which is (wait for it…) to do nothing.

From the docs on NSNotificationCenter's addObserver:

“As a convenience, when built with garbage collection, you do not need to remove any garbage collected observer as the system will do it implicitly.”

And as of the November seed of 10.6, this is also now true of KVO. The seed note “Automatic Removal of Finalized Key-Value Observers When Running Garbage-Collected (New since November seed)” describes the following:

“In Mac OS 10.6, explicit removal of observers when they’re finalized is now never necessary. KVO automatically removes observers as they’re collected. Actually, in Mac OS 10.6 all invocations of -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] and -[NSArray(NSKeyValueObserverRegistration) removeObserver:fromObjectsAtIndexes:forKeyPath:] do virtually nothing when either the receiver or the observer is being finalized (so it’s not very bad for performance to leave them there in applications that still have to run on Mac OS 10.5).”

So at least in Snow Leopard after the November seed, you can just let it ride and the system will take care of cleaning up your KVO and NSNotificationCenter registrations.

As for item #3, well it’s either playing games with regularly invoking NSGarbageCollector's collectExhastively or implementing a dispose pattern.

Published in: on October 23, 2009 at 8:56 am  Comments (1)  
Tags: , , , ,

Two-Way Data Binding in Cocoa

Coming from the .NET world, it seems strange to me that for whatever reason, bi-directional data binding isn’t supported out of the box in Cocoa.

The various provided standard controllers effectively implement two-way data binding. Take for example NSArrayController's contentArray. When binding NSArrayController's contentArray to a collection in your own data model, the NSArrayController uses Cocoa’s KVO based binding technology to observe changes to your data model. Coming to Cocoa with experience from other data binding technologies, this is pretty straightforward and expected behavior.

NSArrayController also pushes updates to your data model, but not through Cocoa’s binding technology. In the reverse direction, NSArrayController caches the information passed to it when a data binding is established. This cached information is used to force feed updated values to the source of the data binding via Cocoa’s KVC technology. It wasn’t initially clear to me that this was being accomplished “manually” by the NSArrayController and that this bi-directional behavior wasn’t something I could expect to happen automatically when implementing my own controllers.

Apple’s documentation doesn’t touch on strategies to implement the kind of two way communication that their standard controllers evidence that I could find. In fact, Cocoa Bindings Programming Topics doesn’t really have a lot to say on the subject of implementing your own controllers at all. As usual, I found solace via Google and the Cocoa community. In particular I found this clear and brief CocoaHeads México presentation to be a really helpful addition to Apple’s documentation when getting up to speed on implementing custom controllers.

Fortunately, Apple’s sample code does a great job of showing an example of implementing a custom controller that performs this kind of two way communication. The BindingsJoysticks sample demonstrates the pattern of overriding your custom controller’s bind implementation and caching the source object and source key path of the bind.

An advantage of the “manual” implementation of the back flow of data from controller to source in Apple’s sample code is a high degree of flexibility and control over exactly when the source of the data bind is updated by your controller. In fact, you can choose to have your source object and your controller be out of sync from each other for a period of time (or forever) if that floats your boat. This can be pretty useful in various situations (interactive mousing with undo/redo comes to mind), but can also be harder to maintain and downright cryptic to a consumer of the controller.

A fairly obvious downside to “manually” implementing the back flow of data from controller to source is, well, the manual part. The extra typing isn’t so bad if you are implementing your one true controller to rule them all, but if you have a number of properties you want to bind, it can be pretty tedious. Consider for example, implementing in the style of Model-View-View/Model (MVVM).

In MVVM, it’s typical to use data binding to glue your view to your view model without either being the wiser. Having not built a large scale Windows Presentation Framework (WPF) application (whose API is architected around the MVVM pattern) I never really got the Kool-Aid pumping through my veins. Proponents of MVVM believe it makes it easier to iterate on user interface, easier to perform headless automated testing of UI functionality, and provides overall more scalable and maintainable implementations. If you are interested in learning more about MVVM, some links to check out are:

In MVVM, there are often a relatively large number of properties across a number of objects that need to be bound to each other. Manually implementing two-way data binding for each such object can be kind of a drag. For that reason, I threw together a little utility class to handle the back flow of values from controller to source (or View to View-Model) for me. The sample code is available at Cocoa Convert on Google Code.

A few caveats before I go on: this is definitely not production code and I use garbage collection. In other words, no effort has been put into retaining objects appropriately and it’s probably a very bad idea to drop this into your own project as is.

An instance of the TwoWayBindingManager class is owned by your custom controller:

#import "TwoWayBindingManager.h"

@interface MyController : NSObject 
{
@private
  ...
  TwoWayBindingManager* _twoWayBindingManager;

It is instantiated when your controller is initialized, and should be disposed of when your controller is disposed of (either in a custom dispose method, or when not using garbage collection in a dealloc):

- (id)init
{
  if([super init] == nil)
    return nil;

  _twoWayBindingManager = 
    [[TwoWayBindingManager alloc] initWithObject:self];

  return self;
}

- (void)dispose
{
  [_twoWayBindingManager dispose];
  _twoWayBindingManager = nil;
}

Your custom controller then needs to override bind and unbind and give the TwoWayBindingManager instance a chance to hook in:

- (void)bind:(NSString *)bindingName
    toObject:(id)observableController
 withKeyPath:(NSString *)keyPath
     options:(NSDictionary *)options
{	
  [super bind:bindingName
	 toObject:observableController
  withKeyPath:keyPath
      options:options];

  [_twoWayBindingManager bind:bindingName
					 toObject:observableController
				  withKeyPath:keyPath
					  options:options];
}

- (void)unbind:bindingName
{
  [super unbind:bindingName];
  [_twoWayBindingManager unbind:bindingName];
}

From the controller side, that’s it! As far as usage goes, you just need to pass in the extra option kWantsTwoWayBinding for any bindings that you want to be bi-directional:

[cont bind:@"someControllerProperty" 
  toObject:self 
 withKeyPath:@"someSelfProperty"
   options:[NSDictionary dictionaryWithObjectsAndKeys:
  		    [NSNumber numberWithBool:YES], 
		    kWantsTwoWayBinding, nil]];

The major trade-off of the TwoWayBindingController approach is less flexibility and control over how closely synchronized the properties of your custom controller are kept to your data source. For situations where you are willing to trade that kind of control for the ease of bi-directional data binding, an approach like the TwoWayBindingController may just save you a lot of typing and bug hunting!

The sample code accompanying this article is available at Cocoa Convert on Google Code.

Published in: on May 31, 2009 at 10:16 pm  Comments (3)  
Tags: , , ,

Pattern Muscle Memory

Sometimes I catch myself applying a particular pattern in an architecture / application design almost without consciously thinking about it. One of the side benefits of flailing around in Cocoa and Objective-C is the disruption of my “pattern muscle memory”.

A recent example is in the implementation of the model layer of the graphical authoring tool I’m working on. One very basic required feature is the ability to delete a graphical element. The element can be deleted in the usual ways: the user pressing the delete key, the user selecting delete from the edit menu, etc. These actions ultimately invoke the same code and remove the item from the data model. There are other ways that the element might be deleted too: as a result of a cut operation, as the result of a synchronization or merge operation with an external source (like importing data from another file), etc.

My pattern muscle memory would normally have me tackle the ability to undo/redo this operation using classic “gang of four” style command and memento patterns; creating concrete implementations of an abstract command for each action.

In this case, being a new Cocoa programmer, my C#/.NET pattern muscle memory was disrupted by the NSUndoManager’s cool ability to package up “ordinary” invocations rather than requiring any special sub-classing or glue code. Now, I could certainly implement this kind of thing in .NET using reflection, etc, but I would have to implement it rather than using it “off the shelf”. Besides, my pattern muscle memory would have kicked in before I really had given it too much thought.

For my delete implementation, I chose to use one of the common Cocoa approaches exemplified in Aaron Hillegass’ book of using KVO to observe the removal of the object from it’s collection and registering it’s inverse (an insertion) on the undo stack. When KVO tells me that the object was added, I register the inverse of that operation (a deletion) on the undo stack.

One common challenge I’ve faced in the past is what to do about side effects or otherwise dependent actions of the principal action occurring. In the case of deleting my graphical object, there are several side such effects. One example is the need to modify connected or constrained graphical objects. In certain situations, an extreme side effect is the need to delete or create related objects, allocate unique identifiers, etc.

My pattern muscle memory typically has me encapsulate these dependent actions along with the implementation of my original user operation, in this case, the delete. One complication of this approach is that as the application scales and multiple developers work on the code base, it can be hard to ensure that everyone consuming the model uses the same high level delete implementation.

In the case of the delete key, the delete menu item, etc, it’s dead simple to make sure the same high level code (with it’s encapsulated side effect behavior) is invoked. As more complex features (such as the merge example) find themselves needing to delete the graphical object (along with performing all of it’s side effects) the requirement to use the common high level delete implementation can get obscured. Especially when the various types of consumers haven’t been anticipated in the design of the model’s API. I’ve found the murkiness (and naughtiness) increases when a generalized data model framework is being used, as it invites direct access to manipulating the data model via it’s APIs. Such is definitely the case with Core Data.

In the past, my pattern muscle memory has had me implement intermediate model layers that encode the side effects, but it has always seemed like such a waste of time and effort to obfuscate direct access to the generalized data model framework APIs with intermediate layers.

In my Cocoa implementation, I choose to implement my data model side effects in KVO observers. I did this so that deleting my graphical element using the Core Data API results in the requisite side effects and dependent data model changes. The main reason I did this is to avoid requiring special discipline or knowledge of the side effects on the part of the consumer of the model. My KVO observers however, also implement the undo/redo registration as I touched upon above. The problem with this approach when naively done is the exponential accumulation of invocations in the undo and redo queues. Each KVO notification from successive undo and redo operations results in performing the side effects and dependent operations anew (in addition to the queued undo/redo invocation).

This is easily rectified by checking to see if our KVO notification is happening as a result of an undo/redo operation (i.e. [NSUndoManager isUndoing] or [NSUndoManager isRedoing]) before performing side effects and dependent operations. If we are in the midst of an undo or redo, we let the invocations on the queue take care of the side effects and dependent operations, but don’t ourselves reissue them as a result of the KVO notification.

Sure I could have implemented all this in C# / .NET, or Java or JavaScript for that matter, but it’s not set up “out of the box” for it, and besides, my pattern muscle memory would have kicked in first anyway.

The bottom line result is a clear and compact model implementation that is easier to implement, extend and maintain over time, one that does not constrain it’s consumers to specialized APIs or require specialized knowledge.

Well, at least that is the theory… Time will tell, but for now I am love-hating my pattern muscle memory disruption.

Published in: on May 20, 2009 at 11:28 pm  Comments (1)  
Tags: , , , ,

Faulting Fun

Managed memory is awesome. Generally speaking, I would rather gouge my eyes out than go back to manually allocating memory.

It’s not that I can’t do it. I’ve been programming for long enough that I started out manually managing memory in the progression from 6502 assembly to C to C++, etc. True, the past few years I’ve been much farther away from embedded system code than I used to be in the days of the Super Nintendo, Atari Jaguar, PlayStation, et al. It’s just that I’d rather spend my time expressing “big ideas” (cue eye rolling now) than tweaking out string memory management on my sub three pound laptop with 4GB of memory.

I’m not sure I would be able to handle Cocoa and Objective-C programming without automatic memory management, but one recent friction point in my love affair with the Cocoa APIs is the dawning realization that there are a ton of subtle API architecture and implementation choices that were made before the move to Objective-C 2.0 and managed memory.

I’m not talking about fundamental incompatibilities between Cocoa API architecture and managed memory. I’m just talking about stumble inducing speed bumps.

A recent example I’ve tripped over is in combining Core Data and KVO. I am using both raw KVO and data binding heavily to glue together Core Data with the view model and view of the application I’m working on. In one instance, when a Core Data document (well, really an associated NSManagedObjectContext) is loaded, I execute a fetch request to obtain a set of peer “root” NSManagedObjects. I then register to observe some relationships and attributes on the resultant NSManagedObjects via KVO and then continue on with the rest of the application.

Later during the program, when new “root” NSManagedObjects of this particular entity type are created, I do the same thing (i.e. register to observe some relationships and attributes using KVO).

When attributes on these recently added “root” objects are changed, the user interface reflects the changes as expected, however when attributes on loaded “root” objects are changed, the user interface does not reflect the changes. WTF right?

After a curse filled hour or two (and copious amounts of caffine for focus) the problem turned out to be with my original fetch request and register using KVO. When I performed the fetch, I was not keeping a reference to the NSManagedObjects I obtained. Eventually after a garbage collection cycle or two, those initial NSManagedObjects were collected, and the underlying Core Data entity instances were turned back into fault (i.e. are dumped from memory). A very cool feature of Core Data, but very not ideal in this case.

When I later executed a fetch request to obtain one of these initially loaded “root” NSManagedObjects, Core Data created new NSManagedObject instances for me, bringing the data they represent back into memory from the persistent store. At this point, they are NOT the same NSManagedObject instances that I registered to observe with KVO (those instances are gone) because KVO did not keep strong references to the original objects, and neither did I.

Bottom line, while I am conceptually changing values on the same Core Data entity instances that I initially registered to watch with KVO, they are not actually the same NSManagedObject instances (thanks to garbage collection and the efficiency / coolness of Core Data dumping data from memory that’s not currently needed). Hence the lack of change in the user interface. The observed objects didn’t change, they were garbage collected!

In this case, it’s an easy fix; I just retain strong references to my “root” NSManagedObjects. I don’t really want these objects coming in and out of memory anyway.

I suspect had garbage collection been in heavy use by the designers and creators of KVO and Core Data when they were conceived and implemented, there might have been some subtle changes to their approach. Or maybe at the very least to the documentation.

I’m not really complaining; both of these systems are damn cool and when I’m not learning how to avoid tripping over my own feet, they are accelerating the crap out of my development.

Here’s looking forward to the days of less tripping per stride!

Published in: on May 19, 2009 at 6:19 pm  Comments (4)  
Tags: , , , ,

Self Observation

As far as I can tell, you can’t count on the order of observer registration for KVO to relate to order of notification. This is a bummer because it can lead to really subtle bugs for certain KVO and bindings patterns. My conclusion is to avoid those patterns, but if you’re interested in the details (and especially if you can point out a solution / flaws in my tests), read on!

In this particular case, I have a base drawable class (DGDrawable) that exposes a collection of child drawables.  I have a drawable sub-class (called DGNode) that adds a collection of DGPort objects (another DGDrawable sub-class).  DGNodes have special additional functionality associated with their child ports, but all the base class functionality of DGDrawable with respect to their children still applies.  DGNodes also repeat this pattern with other types of DGDrawable children, but for this example, I’ll just focus on the ports collection.

So what I’d like to be able do is have DGNode instances observe their port collection and edit the membership of their children collection to enjoy all the default DGDrawable behavior vis a vis child DGDrawables.

So for example, in the DGNode initializer, it registers to observe itself:

[self addObserver:self
       forKeyPath:@"ports"
          options:(NSKeyValueObservingOptionNew | 
                   NSKeyValueObservingOptionOld)
          context:nil];

And in it’s observer method, it edits it’s children collection to reflect changes to the ports collection:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
  int changeKind = [[change objectForKey:
    NSKeyValueChangeKindKey] intValue];
  if([keyPath isEqualToString:@"ports"])
  {
    if(changeKind == NSKeyValueChangeSetting ||
      changeKind == NSKeyValueChangeRemoval ||
      changeKind == NSKeyValueChangeReplacement)
    {
      NSMutableArray* children = 
        [self mutableArrayValueForKey:@"children"];
      for(DGPort* port in 
        [change objectForKey:NSKeyValueChangeOldKey])
      {
        [children removeObject:port];
        [port setNode:nil];
      }
    }
    if(changeKind == NSKeyValueChangeSetting ||
      changeKind == NSKeyValueChangeInsertion ||
      changeKind == NSKeyValueChangeReplacement)
    {
      NSMutableArray* children = 
        [self mutableArrayValueForKey:@"children"];
      for(DGPort* port in 
        [change objectForKey:NSKeyValueChangeOldKey])
      {
        [port setNode:self];
        [children addObject:port];
      }
    }
  }
}

Now, let’s say that another object external to the DGNode wants to use or observe the ports collection.  The addition of a port into the children collection is not guaranteed to happen with respect to when the external observer is notified (even though the DGNode registered it’s observation “first”). So in effect, the outside observer is told about changes to the DGNode when it’s in an “intermediate” state (i.e. the ports have been updated, but not the children collection).

In the context of a larger set of dependent connections and data binding, forgetting that there is no guarantee about the lack of order can make for some real fun debugging!

So my lesson learned for the day: architect order dependency out of KVO (and therefore data binding) from the get go to avoid having to continually prune away subtle ordering bugs .

Ahh, good times!

Published in: on May 11, 2009 at 5:45 pm  Comments (3)  
Tags: , ,
Follow

Get every new post delivered to your Inbox.