Skip to main content

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?



Source: Tips4all

Comments

  1. 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.

    ReplyDelete
  2. 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.

    ReplyDelete
  3. Change
    @property (nonatomic, retain) id reference;
    to
    @property (nonatomic, assign) id reference;

    Why bother to retain the object implementing the protocol? All you need is a pointer to the object by which we can call methods declared in your protocol.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex