2

我试图了解当在操作的完成块中引用对象时,让对象在其 dealloc 方法中取消网络操作是否是个好主意。

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

我有一个User带有属性的对象pictureUser有一个[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) a NSOperation ,该 a 将及时启动 aNSURLConnection以下载图像。当操作成功完成时,成功块将被调用。

我使用weakSelf是因为我不希望块保留我的用户对象(并防止它被释放),我希望用户在获得释放时负责取消现有操作(如果存在)。
所以 User dealloc 方法看起来像这样:

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

    [super dealloc];
}

但是好像虽然我在dealloc方法中取消了操作,但是有时候用户拿到dealloc之后EXC_BAD_ACCESS调用成功块,我就排队了weakSelf.picture = downloadedImage

为什么会这样?是不是该操作即使被取消也会尝试完成连接?

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

更新: 我注意到操作状态是Finished = YES,似乎使用我使用的库,当操作完成时,它不会立即执行成功块,而是将成功块与主队列dispatch_async。

所以正确发生的是:
1.用户获取图像->创建操作
2.操作完成->dispatch_async成功块(仍未执行)
3.在成功块执行之前用户dealloc->取消他的所有操作(但不是第 1 步的操作,因为它处于 isFinished 状态)
4. 现在执行成功块 -> 我在尝试引用用户时得到 EXC_BAD_ACCESS。

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

4

1 回答 1

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
       } 
     }
于 2012-07-10T11:51:17.623 回答