我试图了解当在操作的完成块中引用对象时,让对象在其 dealloc 方法中取消网络操作是否是个好主意。
我将尝试用一个例子来解释:
我有一个User
带有属性的对象picture
,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
) 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。
仍然不知道如何解决这个问题..