This weekend I came across a series of tweets from Nick Lockwood explaining why he doesn’t prefix his class category method names, and found fully myself vehemently agreeing with everything he said.
People ask why I don't prefix category methods. It's because prefixes are ugly, and the ONLY reason for categories is to make code beautiful
This is dead-on. Unless you’re specifically trying to override existing behavior1, class categories are nothing but syntactic sugar. There’s nothing to be gained functionally by using a category as opposed to simply a function, or class/instance methods on a custom object that you create. It’s simply aesthetic preference.
@nicklockwood agreed. If 'myMethod' is likely to clash, then use 'myMethodThatIsNotLikelyToClash', not 'ugly_myMethod'.
If you think creating unprefixed class category methods is unsafe because Apple could potentially add a method that collides with yours in the future, please realize that this could also happen to any method on any custom class in your application. Apple adds new methods to NSObject and other commonly subclassed base classes all the time. Categories are hardly the only place where such a problem could arise.
@sdarlington unless you prefix all public and private methods/properties of every class you make, you can't completely avoid collision risk.
If you’re releasing a class category as part of an open-source library, it may make sense to prefix its methods. However, even then I have my doubts. If the library only uses these category methods internally, then yes, prefix them to prevent against collisions with any other open-source code that the developer using your code may have also imported. But again, in this case I’m not sure using a category really buys you very much. If the category itself is expected to be used directly by third-party developers, the original point remains: is using a prefixed category method any cleaner looking than a utility class? I tend to think not.
UPDATE: Both Brian Bonczek and Jared Sinclair have pointed out a benefit of prefixing category methods that I somehow overlooked: to prevent collisions with third-party dependencies that you include. But again I question the general usefulness of third-party categories as opposed to utility classes.
Key-Value-Observing is a divisive API, to say the least. Despite it’s (well-documented) flaws, I personally tend to favor it when wanting to know if a property’s value changes, but most developers I talk to (including bothof my fellow iOS developers here at Tumblr) tend to prefer overriding setters. Here’s a case where I think KVO works slightly better than overriding setters does.
Say you have a custom view controller subclass with a property, and changes to that property’s value will result in some modifications being made to the view controller’s view or subviews. An example from the Tumblr codebase does exactly this:
Of course, there’s a problem with this. Since we’re calling the custom setter before the controller’s view has necessarily loaded, it won’t have the desired effect. At best, the subviews we operate on inside the overridden setter will be nil and our custom behavior won’t be applied. At worst, we’ll refer to self.view in our implementation, the view will be loaded prematurely, and something unexpected could occur.
So how can we fix this? One way is to make sure our setter is called again after the view is loaded, and prevent against the custom logic being executed beforehand:
This should work, but calling a getter and passing it’s return value to the same property’s setter doesn’t strike me as being particularly elegant. What if we factor out our custom logic into a separate private instance method?
Now, we’re still faced with the same issue of needing to ensure that this code runs both A) as soon as the view is loaded and B) any time the property’s value is changed going forward. Thankfully, NSKeyValueObservingOptionInitial provides this exact behavior.
Since we’re no longer overriding the setter, the property’s value can be changed completely independently of the view being initialized. When our view is set-up, we add an observer that is called immediately with the initial property value, and called again whenever the property is changed in the future.
KVO code can be messy, can result in problems if used incorrectly, and certainly isn’t the best tool to use in all situations. But if you ask me, this is a pretty good example of when it does come in handy.
Drew Crawford published a post entitled NSNotificationCenter with blocks considered harmful yesterday. Upon reading, one might get the impression that using the NSNotificationCenter block API is different in some way then using blocks, well, anywhere else. It isn’t.
NSNotificationCenter retains the blocks that you pass to it, and as such, referencing self inside the block will introduce in a nasty retain cycle. This is unfortunate but far from a new revelation; Jim Dovey wrote about this almost exactly two years ago and I got bit pretty hard myself during my earlier days as an iOS developer.
My problem is that Drew’s article seems to imply that using blocks with NSNotificationCenter is worse in any way than using any other block that gets retained by self. Either way, you need to make sure you’re not closing over a strong reference to self or suffer the wrath of the resulting retain loop causing some hard-to-debug side effect. The only thing, in my opinion, that makes NSNotificationCenter blocks slightly dicier is that as Drew points out, the normal LLVM warning is for some reason missing in this instance1.
This isn’t to say that Drew’s article isn’t worth reading; it’s a great read, and you’re almost certain to learn or have something reinforced. Just please know that using blocks at all requires understanding how to use weak references and the consequences of not doing so. I’d recommend reading the article but then following it up with the accompanying Hacker News comment thread, in which Ash Furrow far more eloquently sums up what I’ve been trying to explain with this post:
There’s nothing really magical about this – don’t cause retain cycles, everyone knows __block semantics changed with ARC, keep the returned value from the block-based NSNotificationCenter method, etc. Standard stuff.