ObjC: How bad is to directly assign to a property and the release it?
I'm wondering how bad is the following code for experienced objective-C programmers.
self.request = [[ASIHTTPRequest alloc] initWithUR开发者_运维问答L:url];
[self.request release];
It is definitely less verbose this
ASIHTTPRequest *tmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = tmp;
[tmp release];
But I'm not sure if it is meaningful enough or doesn't lead to bugs.
What do you think?
UPDATE: I don't want to use autorelase pools as my app is going to run on iphone where memory is limited.
UPDATE: I don't want to use autorelase pools as my app is going to run on iphone where memory is limited.
Do use the autorelease pools! Cocoa touch framework itself uses them; making one or two autorelease
'ed objects yourself doesn't change the big picture.
It's true Apple warns you against excessive reliance on autorelease pools on iPhone, like putting hundreads of objects before the pool gets drained after the conclusion of the event dispatch, but excessive avoidance of autorelease pools is also counter-productive!
Nothing is black and white; nirvana is in the middle way.
Why not this?
self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
Or, if this is a class you wrote or have the source for, create a new class method (not instance) that does essentially the same thing (assuming NSURL *
argument):
+ (ASIHTTPRequest *) requestWithURL:(NSURL *)url
{
return [[[self alloc] initWithURL:url] autorelease];
}
Definitely go with the latter, although choose a more descriptive name instead of tmp
. You are responsible for releasing tmp
, but you are not responsible for releasing self.request
, at least not in the context given.
Alternatively, if you don't mind adding things to the autorelease pool, simply do:
self.request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
or
self.request = [ASIHTTPRequest requestWithURL:url];
What you missed is not the difference in verbosity but the memory management difference.
You often see code like this:
ASIHTTPRequest * requestTmp = [[[ASIHTTPRequest alloc] initWithURL:url];
self.request = requestTmp;
[requestTmp release];
You should consider what is happening if the property is retained and old one released in the setter method.
- What this mean is that you create new
request
, refcount is 1. self.request = request
, now ifsetRequest
looks like:- (void)setRequest:(ASIHTTPRequest*)aReq { [aReq retain]; [request release]; request = aReq; }
This means that the object retained the
requestTmp
you passed in and released the old one. Refcount ofrequestTmp
is now 2.After this call you can then release your original
requestTmp
that you created and you are safe because the object retained therequestTmp
- refcount is still 1.
However if you do this:
self.request = [[ASIHTTPRequest alloc] initWithURL:url];
[self.request release];
you end up releasing the request
that the object retained
for its use. Note that you are release object's internal request
where in the original case you released the tmp
but the object keeps it's own retained reference.
So the result is different from the original code.
精彩评论