Private methods in Objective-​C using categories

Photo of a rusted gate in Croatia

Objective-​C is an incredibly flexible language, but there are a few things I don’t think it handles very elegantly — private methods are one of those things. Private methods are important when designing your classes — keeping the implementation of your methods separate to the interface that users of your class see is good practice, and lets you change the way you implement things in future without making users of your class change their code.

Objective-​C has a great feature known as categories. In the words of Scott Stevenson, “a category allows you to add methods to an existing class without subclassing it or needing to know any of the details of how it’s implemented”. My private methods are implemented using an anonymous category on each class. These are also known as “Class Extensions” and they look like this in my .m file:

#import "MyGreatClass.h"

@interface MyGreatClass ()
- (void)MyGreatClass_somePrivateMethod;
@end

#pragma mark -
@implementation MyGreatClass

// Your standard methods for the class go here.

#pragma mark -
#pragma mark Private methods
- (void)MyGreatClass_somePrivateMethod {
  // Implement your private method here.
}

@end

By declaring the method interface inside the class extension, rather than in your header, subclasses and users of your class cannot see the method, and thus can’t use it. However within an instance of your class, the method is still usable!

You’ll notice that I preface my private methods with the name of the current class — I do this to avoid method name collisions with subclasses. It’s not strictly necessary, but it means I don’t have to think as hard when implementing subclasses of my class.

You can do everything you would in a normal class except declare new instance variables. I often use my class extensions to redeclare a public readonly property as readwrite within the confines of the class instance. Another common use in my code are the following two methods:

- (void)MyGreatClass_registerObservers;
- (void)MyGreatClass_unregisterObservers;

These methods are used to set up and tear down any Key/​Value Observers and bindings for the current class. I use these so often that I’ve put together an Xcode class template so that they are included in my classes by default.

Please keep in mind that Objective-​C has no true implementation of private methods — other classes can use these “private” methods if they know the structure of the method in question. With that said, I still believe this is a great way to keep your implementation as clean as possible.

Update

Both Paul and Collin make good points in the comments — you can just declare your private methods inline in your class without using an anonymous category. That will work so long as the declaration occurs before the first use of the method. In my mind, there are two good reasons to use a category:

  • Readability/​cleanliness — I find it a lot easier to group the declarations for my private methods together inside the category block. It’s quite readable and means I can just look at the start of the source for each of my classes to see what private methods are defined;
  • It’s the same when compiled — as I understand it, anonymous categories are compiled into the same space as the methods for the class they are defined for. Functionally — once the code is compiled — there shouldn’t be any difference between the two ways of defining the methods.

Comments

Gravatar for Paul.

In reality, you don’t even need the anonymous category. Objective-​C follows the same resolution rules as C: As long as the function (method) is defined earlier in the file than code that might reference it, the compiler is perfectly happy. The only reason you might need the category is if a method is defined later in the file than the reference to it. Then the compiler needs the prototype.

Posted by Paul on

Gravatar for Collin.

Paul — While you may not need to do this technically, readability is greatly increased by declaring all methods private and otherwise.

Posted by Collin on

Gravatar for Rob Rix.

I use this exact thing for protected methods, except for placing the class extension in a separate header: MyGreatClass+Protected.h. Subclasses import this header in their .m file, and everything else ignores it.

For me, this is exactly the right balance: I can export this API to other classes (e.g. C++-style “friend” classes) without having to resort to hacks, and I don’t have the method declarations cluttering up the public API (or, equally bad, duplicated amongst the subclasses).

Posted by Rob Rix on

Sorry, this conversation has finished.

This post is a bit old now, so I've closed the conversation. If you're keen to keep talking about it, please email me directly.