2012-07-10 37 views
2

我想了解在操作的完成块中引用Object时,是否让Object在其dealloc方法中取消网络操作是个好主意。目标c - 取消dealloc中的操作

我会尝试用一个例子来解释:

我有物业picture一个User对象,User[self fetchPictureFromServer]

- (void)fetchPictureFromServer 
{ 
    NSDictionary *cmdParameters = ...; // set parameters 

    __block User *weakSelf = self; 

    [[AppClient sharedClient] sendCommand:@"getpicture" parameters:cmdParameters success:^(AFHTTPRequestOperation *operation, id response) 
    { 
     // success 
     UIImage *downloadedImage = ...; // get image from response 

     weakSelf.picture = downloadedImage; // set image to user's picture property 
    } 

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     // failed 
    }]; 

sendCommand方法将创建(和入队NSOperationQueue)一个NSOperation,在时间上将启动一个NSURLConnection下载图像。当操作成功完成时,将调用成功块。我使用weakSelf,因为我不希望块保留我的用户对象(并防止它成为dealloc),我希望用户将负责取消现有的操作(如果存在),当他得到dealloc。
所以用户dealloc方法是这样的:

- (void)dealloc 
{  
    [[AppClient sharedClient] cancelAllCommandsForSender:self]; 

    [super dealloc]; 
} 

但似乎,虽然我在取消dealloc方法操作,有时成功的块被称为用户后得到的dealloc,我获得EXC_BAD_ACCESS,行weakSelf.picture = downloadedImage

为什么会发生?即使它被取消,操作是否会尝试完成连接?

我知道,如果我只在块中使用self而不是weakSelf,则不会发生这种情况,因为该块将保留用户。但我不想要这种行为,我希望用户在释放时立即获得dealloc,即使存在获取操作。

UPDATE: 我注意到,工作状态isFinished = YES,似乎与我使用的库,当操作完成后,它不会立即执行成功的块,但它dispatch_async的成功阻止主队列。

那么正常发生的事情是:
1.用户获取图像 - 之前的成功块> dispatch_async成功块(还没有执行)
3 - >操作创建
2.操作完成执行用户dealloc - >取消他所有的操作(但不是从step1开始的操作,因为它处于isFinished状态)
4.现在执行成功块 - >当尝试引用用户时,我得到EXC_BAD_ACCESS。

仍然不知道如何解决这个..

+0

这是一个ARC项目? – 2012-07-10 17:53:26

+0

请看看我的更新 – Eyal 2012-07-11 07:38:05

+0

它是一个ARC项目(因为'__block'的语义在ARC下是不同的),并且您的部署目标是5.0+吗? – 2012-07-11 15:36:34

回答

2
[[AppClient sharedClient] sendCommand:@"getpicture" parameters:cmdParameters success:^(AFHTTPRequestOperation *operation, id response) 
    { 
     if(!operation.isCancelled) 
     { 
     // success 
     UIImage *downloadedImage = ...; // get image from response 

     weakSelf.picture = downloadedImage; // set image to user's picture property 
     } 
    } 
+0

如果操作被取消,则不会调用成功块,所以我不认为这是必需的。 – Eyal 2012-07-10 11:52:42

+0

我检查了操作状态,它是“isFinished”,怎么样?那很混乱:( – Eyal 2012-07-10 12:03:06

+0

请看我更新的问题 – Eyal 2012-07-11 07:38:26