开发者

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 if setRequest 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 of requestTmp is now 2.

  • After this call you can then release your original requestTmp that you created and you are safe because the object retained the requestTmp - 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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜