Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In objective-C (iphone), how do I manage the memory of '@protocol' references?

I thought I had a pretty good handle on memory management for objective-c, but I can't figure out the following situation:


@protocol MyProtocol
@end

@interface MyObject : NSObject {
    id<MyProtocol> reference;
}
@property (nonatomic, retain) id<MyProtocol> reference;
@end

@implementation MyObject 
@synthesize reference;
-(void) dealloc {
    [reference release];
    [super dealloc];
}
...
@end

This gives me a "warning: '-release' not found in protocol(s)". Can I safely ignore this error? Or am I doing something horribly wrong?

like image 870
chris.f.jones Avatar asked May 12 '09 23:05

chris.f.jones


People also ask

What is Objective-C memory management?

It is the process by which the memory of objects are allocated when they are required and deallocated when they are no longer required.

How do you conform to a protocol in Objective-C?

Objective-C Language Protocols Conforming to Protocols It is also possible for a class to conform to multiple protocols, by separating them with comma. Like when conforming to a single protocol, the class must implement each required method of each protocols, and each optional method you choose to implement.

What is Autorelease Objective-C?

The -autorelease message is a deferred -release message. You send it to an object when you no longer need a reference to it but something else might. If you are using NSRunLoop, an autorelease pool will be created at the start of every run loop iteration and destroyed at the end.

What is ID in Obj C?

id is a data type of object identifiers in Objective-C, which can be use for an object of any type no matter what class does it have. id is the final super type of all objects.


2 Answers

Yes you can safely ignore this error. An object declared as type id<MyProtocol> may not inherit from NSObject (you do not have to use the Cocoa libraries to program in Objective-C and there are other root classes even in Cocoa such as NSProxy). Since retain (and release, autorelease) are declared in NSObject, the compiler cannot know that the instance declared as type id<MyProtocol> responds to these messages. To get around this, Cocoa also defines the NSObject protocol which mirrors the NSObject API. If you declare your protocol as

@protocol MyProtocol <NSObject>
@end

indicating that MyProtocol extends the NSObject protocol, you'll be set.

like image 107
Barry Wark Avatar answered Oct 28 '22 20:10

Barry Wark


Ordinarily, when you declare an object as id it counts an an "any" object (meaning that Objective-C will let you invoke any method from any class or protocol on the id without warning).

However, when you declare an object as id<SomeProtocol>, the meaning changes. In this case, you are instead saying: I will only invoke SomeProtocol methods on this object.

The method:

- (void)release;

is declared in the NSObject protocol but you have explicitly stated: I will only invoke MyProtocol methods. So the compiler gives you a warning to tell you that you've broken your own promise.

Therefore, instead of:

id<MyProtocol> reference;

you should actually declare:

id<MyProtocol, NSObject> reference;

or:

NSObject<MyProtocol> reference;

since NSObject (the class) implements NSObject (the protocol).

or:

id reference;

which is the broadest of the lot: let me invoke anything on this object and never complain.

You can also (as Barry Wark suggested) have MyProtocol include the NSObject protocol -- although from a design perspective, you normally only do this if implementing MyProtocol necessarily means using NSObject. Normally, we only do this if NSObject and MyProtocol are linked heritarily or semantically.


A little information about the NSObject protocol:

Everything you invoke retain/release/autorelease upon must implement this protocol. As you can infer from this: basically everything implements the NSObject protocol (even though a few things don't descend from the NSObject base class).

Another quick clarification: NSObject (the class) and NSObject (the protocol) are not reimplementations of the same API. They are split as follows:

  • NSObject (protocol) implements everything required to handle/inspect an existing object in a generic sense (retain/release, isEqual, class, respondsToSelector: etc).

  • NSObject (class) implements less generic methods: construction/destruction, thread integration, scripting integration.

So in most senses, the protocol is the more important of the two. Remeber that the class includes the protocol so if you descend from NSObject, you get both.

like image 25
Matt Gallagher Avatar answered Oct 28 '22 18:10

Matt Gallagher