Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code example on Apple's dev site declare three interfaces for the same class?

I'm diving into iOS development while trying to grasp Objective-C and I'm still in that phase where, ever where I look, I see things that don't make any sense to a veteran C programmer like myself. In this Game Kit example on Apple's dev site, one of the header files declares a class interface, three different times...

@interface SessionManager : NSObject <GKSessionDelegate> {
    NSString *sessionID;
    GKSession *myGKSession;
    NSString *currentConfPeerID;
    NSMutableArray *peerList;
    id lobbyDelegate;
    id gameDelegate;
    ConnectionState sessionState;
}

@property (nonatomic, readonly) NSString *currentConfPeerID;
@property (nonatomic, readonly) NSMutableArray *peerList;
@property (nonatomic, assign) id lobbyDelegate;
@property (nonatomic, assign) id gameDelegate;

- (void) setupSession;
- (void) connect:(NSString *)peerID;
- (BOOL) didAcceptInvitation;
- (void) didDeclineInvitation;
- (void) sendPacket:(NSData*)data ofType:(PacketType)type;
- (void) disconnectCurrentCall;
- (NSString *) displayNameForPeer:(NSString *)peerID;

@end

// Class extension for private methods.
@interface SessionManager ()

- (BOOL) comparePeerID:(NSString*)peerID;
- (BOOL) isReadyToStart;
- (void) voiceChatDidStart;
- (void) destroySession;
- (void) willTerminate:(NSNotification *)notification;
- (void) willResume:(NSNotification *)notification;

@end

@interface SessionManager (VoiceManager) <GKVoiceChatClient>

- (void) setupVoice;

@end

I see that each interface is different, but specify the same class name.

  1. What's the reason for this?
  2. I've also noticed this same behavior in other code examples, only instead of declaring multiple interfaces in the header file, you'll see an additional @interface block declared towards the top of the .m implementation file, typically above the @implementation block. Why?

Thanks so much in advance for your wisdom!

like image 771
BeachRunnerFred Avatar asked Jul 28 '10 15:07

BeachRunnerFred


2 Answers

These are called Categories, and you can see them by the parentheses after the class name.

They're used to group methods into chunks instead of having them all in one big bunch. They can also be placed separate from the main class declaration. This is particularly useful inside .m files, where you may need to create utility methods for your class, but you don't want them visible to other objects for any reason (so you don't put them in the .h, which is imported by the other classes). Another common use is to group methods which correspond to a certain logical category, informal protocol, or what have you. Categories can be named (@interface MyClass (MyCategory)) or anonymous (@interface MyClass ()). The latter is usually used for generic private methods in your header.

(The reason you need categories to declare private methods in your .m is so the compiler knows about the methods — otherwise, you'll get a warning when you try to call such a method.)

Also, you can use categories to add methods to existing classes. For example, UIKit contains a category on NSString called NSString(UIStringDrawing). Or if you wanted to make your own:

@interface NSString (MyFoo)
+ (NSString *)fooString;
@end
//... somewhere else...
@implementation NSString (MyFoo)
+ (NSString *)fooString { return @"foo!"; }
@end

Note that you can't add instance variables with a category.

like image 183
jtbandes Avatar answered Sep 28 '22 01:09

jtbandes


It is not defining the interface 3 times - there is only one interface.

what you are seeing are categories that add methods to the class

There is a base interface that defines the attributes and some methods - there is only one of these ant it defines how the object is stored in memory and is the only one that is needed.

Objective C looks up methods at run time. These methods do not need to be found at compile time and thus do not need to be declared in headers/interfaces etc. If they are not declared and you code calls them then you will get compile time warnings.

In this case one category with an empty name is used for private functions. I usually only put this interface in the .m file of the class so is not visible to other code as not in a header.

The second category is to add the methods to make SessionManager meet the GKVoiceChatClient protocol. The usual reason for doing this is to group code covering a specific behaviour together.

Another reason for using categories is to add methods to an existing class like NSString -you can create your own category adding methods without subclassing the class as you have to do in many other OO languages including Java and C++

like image 21
mmmmmm Avatar answered Sep 28 '22 01:09

mmmmmm