Private Methods

Fri, Aug 8

One common complaint for many new to Objective-C is that the language lacks support for private methods within a class. There are compiler directives for instance variables: @private, @protected (the default) and @public. However, if you want to hide methods, there is no specific directives to help. The example here builds on the previous post on working with categories.

Ultimately, there is no means to make a method private in Objective-C. However, one can hide methods in a class as I show here. It’s important to understand, this still does not make the methods private, it just makes them “harder to find” if you will.

To implement hidden methods (instance and/or class) you can use categories . Let’s begin with a file called SomeClass.h, the interface definition for SomeClass.

1
2
3
4
5
6
7
8
9
10
11
12
// ===========================
// = File: SomeClass.h
// = Interface for SomeClass
// ===========================
#import <objc/Object.h>
 
@interface SomeClass : Object
 
-(void) msg;
+(void) classMsg; 
 
@end

Nothing too interesting here, simply an interface declaration for a class with two methods: msg and classMsg . By definition (of the language) both methods are publicly accessible. Now, let’s look at the corresponding implementation file shown below. Begin at the bottom where I write the implementation for the two methods above. Again, nothing new, so far.

Now, if you start at the top of this file, notice how I’ve added an interface for SomeClass (similar to the interface definition above), and specified this definition as a category by enclosing the word hidden in a set of parenthesis. It’s important to note, the word hidden is simply my own designation as a note to reflect that I am intending to hide this interface definition, there is no significance to using this specific word. Just below the definition, I write the code for the two methods in the category.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// ===========================
// = File: SomeClass.m
// ===========================
#import "SomeClass.h"
#import <stdio.h>
 
// =================================
// = Interface for hidden methods
// =================================
@interface SomeClass (hidden)
 
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod; 
 
@end
 
// =====================================
// = Implementation of hidden methods
// =====================================
@implementation SomeClass (hidden)
 
+(void) hiddenClassMethod
{
  printf( "Hidden class method.\n" );
}
 
-(void) hiddenInstanceMethod
{
  printf( "Hidden instance method\n" );
}
 
@end
 
// ================================
// = Implementation for SomeClass
// ================================
@implementation SomeClass
 
-(void) msg
{
  printf("Inside msg()...\n");
 
  [self hiddenInstanceMethod];
  [SomeClass hiddenClassMethod];
}
 
+(void) classMsg
{
  printf("Inside classMsg()...\n");
}
 
@end

To see what this does for us, look at the code below, followed by the screenshot:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ===========================
// = File: Main.m
// ===========================
#import "SomeClass.h"
 
int main (int argc, char *argv[])
{
  SomeClass *ptr = [[SomeClass alloc] init];
 
  // Display message (including messages from hidden methods)
  [ptr msg];
 
  // Call a class method
  [SomeClass classMsg];
 
  // Compile warning (can't access hidden instance method)
//  [ptr hiddenInstanceMethod];
 
  // Compile warning (can't access hidden class method)
//  [SomeClass hiddenClassMethod];  
 
  return 0;
}

Notice how I can access the hidden instance and class methods from within the class. However, if I remove the comments from lines 17 and 20, to attempt access to the hidden methods, the compiler generates the following warnings:

I’m not sure if this is the only means to hide methods. If you know of another way (and have a code example), please post a comment.

The output of the application is shown here:

Download the code and give this a try within Xcode.

14 comments

Ondra (http://www.ocs.cz) has passed along another means to accomplish the same end result, without using categories:

@interface X:NSObject
-(void)published;
@end

@implementation X
-(void)unpublished { … }
-(void)published { … [self unpublished]; … }
@end

The trick here, is that the unpublished method is not defined in the interface, yet there is an implementation of the method in the implementation section. The end result here is that you don’t have two separate implementation sections.

I still prefer the idea of using categories as it make the implementation feel more akin to a publicly declared API (through SomeClass.h) and an additional (private) API for internal use by the class.

A personal preference to be sure…

by john on Aug 14, 2008. #

I prefer the category approach as well, mainly because I like to put “private” methods at the end, but I agree it’s a matter of preference. Note that Ondra’s approach only works if you can arrange your private methods in such a way that they are defined before they are called. In rare cases, private method X calls private method Y, and method Y also calls method X.

by Andy Lee on Aug 14, 2008. #

Change Main.m to include the following additional lines and the compiler warnings disappear. This is an unfortunately common pattern used to expose private API that oft produces maintenance headaches in the future.

#import “SomeClass.h”

@interface SomeClass (ExposingThePrivateParts)
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod;
@end

int main (int argc, char *argv[])

by bob on Aug 14, 2008. #

An alternative way to declare a private class method is described in the Objective-C 2.0 documentation.

If you are writing your own class, you can add private methods that are implemented directly within the main implementation block of the class by declaring an empty category. eg:

@interface MyObject : NSObject
{
    NSNumber *number;
}
- (NSNumber *)number;
@end
 
@interface MyObject ()
- (void)setNumber:(NSNumber *)newNumber;
@end
 
@implementation MyObject
 
- (NSNumber *)number
{
    return number;
}
- (void)setNumber(NSNumber *)newNumber
{
    number = newNumber;
}
@end

This way you don’t have to write a separate @implementation block for the private methods. Probably best to use this for methods that are only used within the class itself.

by stompy on Aug 14, 2008. #

This is a fantastic resource John! This post in particular was really helpful for an “old” Java developer like myself. Getting my head around the crazy syntax of ObjectiveC is one of the biggest hurdles I have learning to develop for iPhone. Keep up the great work!

by Rodney on Aug 16, 2008. #

The method which I read in the O’Reilly ‘Learning Cocoa’ book – which in my opinion is slightly cleaner:

1) Declare the private methods in a separate .h file (with a file name like “SomeClassPrivate.h”).
2) Tag this interface with a (private) category.
3) Import both the SomeClass.h & SomeClassPrivate.h into your implementation .m file

The benefits are:
Increased separation of code – the private interface is apart from the public (still)
The private methods can be placed anywhere in your implementation (the whole reason for header files in the first place).

by Matt on Jun 15, 2009. #

The issue of private methods is best solved with the Pointer-to-Implementation pattern. The implementation class may have whatever methods, but its instance (and even the methods it exposes) is kept in the private fields and is not accessible from the outside world.

by Blajer on Mar 10, 2010. #

Thanks Blajer, any code example(s) you can provide to add some additional insight?

by John Muchow on Mar 10, 2010. #

A very simplified example follows:

// ===========================
// = File: SomeClass.h
// = Interface for SomeClass
// ===========================
#import 
 
@class SomeClassImpl;
 
@interface SomeClass : Object {
  SomeClassImpl *myImpl;
} 
-(int) msg;
+(void) classMsg; 
@end

—————————-

// ===========================
// = File: SomeClass.m
// = Implementation for SomeClass
// = NB: the pImpl class is both declared and its implementation defined here.
// ===========================
 
//The hidden interface goes here. These methods will not be available for the outside world.
@interface SomeClassImpl : NSObject {
}
+(void) hiddenClassMethod;
-(void) hiddenInstanceMethod; 
@end
 
@implementation SomeClass
-(id) init {
  if (self = [super init]) {
    myImpl = [[SomeClassImpl alloc] init];
  }
  return self;
}
 
-(int)msg {
  return [myImpl hiddenInstanceMethod];  //These will be perfectly hidden: no instance is leaked.
}
 
+(void) classMsg {
  [SomeClassImpl hiddenClassMethod];  //Well, you can't _really_ hide class methods
}
 
-(void) dealloc {
 [myImpl release];
 [super dealloc];
}
@end
 
@implementation SomeClassImpl
...
@end

by Blajer on Mar 10, 2010. #

I’m fairly new to Obj C; all of the above was useful and thought provoking. I was fine with the idea of simply defining “private” methods at the top of the implementation file. But I ran into an odd problem: if you have more than one arg, the compiler cries that it’s looking for an “;” before the second arg at the point where the message is invoked:

– (void)logMessageByTouch:(UITouch *)touch withDescriptor:(NSString *)desc {

then later a compiler error:

[self logMessageByTouch:activeTouch withDescriptor:@"touchesBegan"];

The compiler is fine when I specify the method in the header, so it’s not my syntax. Maybe I’m missing something (I was surprised). To eliminate this compilation problem, and to avoid order of function definition dependencies (mentioned above), one can declare an @interface for a private category at the top of the .m file. Not sure if this is acceptable but it works:

@interface MyClass(private)
- (void)logMessageByTouch:(UITouch *)touch withDescriptor:(NSString *)desc;
// other private methods here
@end

@implementation

by Joe on Mar 26, 2010. #

Thanks Blajer for this simple mechanism for hiding an interface. A good addition to the book of tricks. This certainly though is not a design pattern to use in order to maintain object oriented code. There’s a big difference between a good OO design and making use of private methods for internal methods, and the desire to protect IP by wanting to hide the internal interface. To be fair the OP did seem to have some desire to hide “private” methods.

For general design I think the categories or extensions (“anonymous” categories) mechanism is better suited to keeping private methods separate from the public interface. This certainly would fit better when implementing and maintaining a UML design and/or keeping the internal methods separate from the object interface.

by John on Nov 10, 2010. #

The problem with categories is that, with Objective-C, you can send an object a message even if it is not defined in the interface. So declaring a method in an extension does not keep anyone from actually calling the method. With the pimpl pattern, this is impossible, since you don’t have access to the object whose method you want to call.

by Blajer on Nov 11, 2010. #

Great one, thank you all for helping me

by Dharmateja on Jul 20, 2011. #

Is it just me or did most of the commenters above not understand that the warnings were a desired feature and that you were trying to show how to HIDE methods, not how to make hidden methods visible?

If you need to call methods from main(), they shouldn’t be hidden in the first place.

by Pedant on Sep 26, 2011. #