Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
346 views
in Technique[技术] by (71.8m points)

iphone - ASIHTTPRequest / ASIFormDataRequest - referencing request object within blocks under ARC

Very similar to this question, I am trying to convert a project that uses ASIHTTPRequest & ASIFormDataRequest to ARC.

In my view controller classes, I often refer to and use properties of the request object in the completion blocks (looking at the response code, response data etc):

__block  ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:SOME_URL]];    
[request setCompletionBlock:^{   

    if([request responseStatusCode] == 200) ....etc

When converting to ARC I get the warning:

Capturing 'request' strongly in this block is likely to lead to a retain cycle

What is the proper way to do this?

Another SO user notes in the previous thread that simply adding __weak may cause the request to be released before the completion of the block, which I believe to be true.

How can I properly reference these properties in completion/failure blocks under ARC?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(I read your comment to the other question)

After implementing a few more modules using ASIHTTPRequest, I learned that the best way was to keep a strong reference to your request object. In your case, you can do:

self.request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:SOME_URL]];
__weak ASIFormDataRequest *weakRequest = self.request; // __block directive not needed since we only access the instance's properties. 
[self.request setCompletionBlock:^{   

    if([weakRequest responseStatusCode] == 200)
    // ...

This way you can still control self.request even after you start the request (e.g. for cancelling). You can do self.request = nil; when you're ready to release your request, maybe inside your completion block or self.request's parent object's cleanup methods.

Update:

If you're targeting pre-iOS 5, then the common ground stands: use __unsafe_unretained instead of __weak. This is OK because looking at ASIHTTPRequest.m, the blocks are nil'ed out in its dealloc() (i.e. they shouldn't get executed). Although I haven't tested that yet, so make sure to still test with NSZombies enabled.

Note:

The only safe way to cancel an ASIHTTPRequest object is to call its clearDelegatesAndCancel method. I've been bitten by some nasty bugs when I was just using the plain cancel one.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...