iOS KVO Singleton "Bug"
Apr 12, 2012
Dick Brouwer
1 minute read

My (least) favorite iOS ‘bug’ to-date

Sometimes you get stuck, very stuck and nobody seems to be able to point you in the right direction. This was one of those moments. The gist of it goes as follows:

We are instantiating singletons using a very efficient approach as suggested in the book: iOS 5 Programming Pushing the Limits:

At the same time, we observe a property of this shared instance using KVO. Now here is the tricky part. iOS internally implements KVO using class swizzling. This basically means that when you first call addObserver:forKeyPath:options:context: on an object, the framework creates a new KVO subclass of the class and converts the observed object to that new subclass (as I found out after a while). Well, this doesn’t work in combination with the suggested +initialize method to create singletons. In fact, initialize is called twice (once for the superclass, and once for the internally generated subclass).

Conclusion: if you are using KVO, create a (non-strict) singleton using the approach below, it will save you some headaches.

+ (UserManager *)sharedManager {
    static dispatch_once_t once;
    dispatch_once(&once, ^ {
        _sharedManager = [[self alloc] init];
    });
    return _sharedManager;
}


comments powered by Disqus