Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this property need the 'retain'?

Given the following definition of a class with retain properties:

@interface FeedEntry : NSObject<NSCoding>
{
    NSURL*  url;
    NSData* source;
}

@property (retain) NSURL*   url;
@property (retain) NSData*  source;
@end

@implementation FeedEntry

@synthesize url;
@synthesize source;

-(void)encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:url     forKey:@"url"];
    [coder encodeObject:source  forKey:@"source"];
}

Why does the url property in initWithCoder method need the "retain":

-(id)initWithCoder:(NSCoder*)coder
{
    url = [[coder decodeObjectForKey:@"url"] retain];
    source  = [coder decodeObjectForKey:@"source"];

    NSLog(@"got url=%@\n", url);
    return self;
}

Specifically, why doesn't the synthesized "get url" method retain the object? (I'm guessing the source property will need a retain as well).

like image 790
Justicle Avatar asked May 18 '09 07:05

Justicle


1 Answers

Quick answer:

When you set:

url = [[coder decodeObjectForKey:@"url"] retain];

you are not using the @property. You are manually setting the value of the instance variable url. You must, therefore, also manually retain the value.

To set the variable using the synthesized properties, you would instead call:

[self setUrl:[coder decodeObjectForKey:@"url"]];

or

self.url = [coder decodeObjectForKey:@"url"];

Either of these forms would make use of the synthesized methods, and handle the retain automatically.

Details:

In Objective-C, the @property and @synthesize keywords automatically create the getter and setter methods for you:

@interface MyClass
{
    id someValue;
}
@property (retain) id someValue;
@end

@implementation MyClass
@synthesize someValue;
@end

Is equivalent to:

@interface MyClass
{
    id someValue;
}
- (id)someValue;
- (void)setSomeValue:(id)newValue;
@end

@implementation MyClass
- (id)someValue { return someValue; }
- (void)setSomeValue:(id)newValue
{
    [newValue retain];
    [someValue release];
    someValue = newValue;
}
@end

This creates an important distinction between the "internal" member variable and the property having the same name. If you reference the member variable by name, you are bypassing the synthesized property methods.

like image 107
e.James Avatar answered Sep 22 '22 23:09

e.James