开发者

alloc + init with synthesized property - does it cause retain count to increase by two?

开发者 https://www.devze.com 2023-01-07 19:17 出处:网络
I\'ve seeen the following snippet quite a bit: In the header: SomeClass *bla; @property(nonatomic,retain) SomeClass *bla;

I've seeen the following snippet quite a bit:

In the header:

SomeClass *bla;
@property(nonatomic,retain) SomeClass *bla;

In the implementation file:

@synthesize bla;

and then

self.bla = [[SomeClass alloc] init];

I think that this assignment puts the retain count for 'bla' up by two; once through the alloc/init call, then through the retain that we asked to happen through the synthesized property setter.

As a result, I normally declare my properties like this:

In the header:

SomeClass *_bla; // note the underscore
@property(nonatomic,retain) SomeClass *bla;

In the implementation file:

@synthesize bla = _bla;

and then

_bla = [[SomeClass alloc] init];

Provided my initial 开发者_Python百科assumption is correct - I'd be interested to hear whether there is 'right' way to do this, i.e. the declaration, initialisation and memory management of properties?


Yes, you are right - using the synthesized setter of a retain property would increase the ref-count on an instance you already own (as alloc implies ownership).

Just go with the second form you mentioned in your initializers:

_bla = [[SomeClass alloc] init];

... and remember to fix the retain count otherwise, e.g.:

self.bla = [[[SomeClass alloc] init] autorelease];


I think that this assignment puts the retain count for 'bla' up by two;

True.

I'd be interested to hear whether there is 'right' way to do this

Your last piece of code is the right way, but the leading underscore is not recommended. The property and the ivar can share the same name. Just

@interface Foo : Bar {
  SomeClass* bla;
}
@property (nonatomic, retain) SomeClass* bla;
@end

@implementation Foo
@synthesize bla;
-(id)init {
   ...
   bla = [[SomeClass alloc] init];
   ...
}
-(void)dealloc {
  [bla release];
  ...
  [super dealloc];
}

is enough.


Some people may use

SomeClass* foo = [[SomeClass alloc] init];
self.bla = foo;
[foo release];

or

self.bla = [[[SomeClass alloc] init] autorelease];

in the -init method, but I strongly discourage it, as this calls unnecessarily many methods, and you cannot guarantee the behavior of the setter.


It looks like the core problem here is a misunderstanding of object ownership semantics in Cocoa. For every init, copy or retain called on an object a call to release or autorelease must be made. What's happening here is that the call to init doesn't have a matching call to release or autorelease.

I think what's confusing here is that the dot-notation for property assignment is syntactic sugar for a method call. So it looks like it's just an assignment when in actuality it's a call to a property setter.

self.bla = [[SomeClass alloc] init];

is not the same thing as:

bla = [[SomeClass alloc] init];

The former translates into:

[self setBla: [[SomeClass] alloc] init]];

while the latter is literally an assignment.

To fix your issue all you really need to do is ensure that the code that calls init calls autorelease so that the retain count will be decremented after the retain call by the setter.


There is no double count. The setter created by by synthesize does a release before doing a retain. See Stanford class on objective c class 3 as referenced on the apple website. It is also worth noting that in case of iboutlets the alloc init is not needed as it is performed through loading of the xib file

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号