我试图了解当操作的完成 block 中引用对象时,让对象在其 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
> 下载图像。当操作成功完成时,将调用成功 block 。
我使用 weakSelf
因为我不希望该 block 保留我的 User 对象(并防止其被释放),我希望用户负责取消现有操作(如果存在)当他被释放时。
所以 User dealloc 方法如下所示:
- (void)dealloc
{
[[AppClient sharedClient] cancelAllCommandsForSender:self];
[super dealloc];
}
但似乎虽然我在 dealloc 方法中取消了操作,但有时在用户获取 dealloc 之后调用成功 block ,并且我得到 EXC_BAD_ACCESS
行weakSelf.picture = downloadImage
。
为什么会发生这种情况?是否该操作即使被取消也会尝试完成连接?
我知道如果我在 block 中只使用 self 而不是weakSelf,这种情况就不会发生,因为 block 将保留 User。但我不想要这种行为,我希望用户在释放时立即得到dealloc,即使存在获取操作。
更新: 我注意到操作状态 isFinished = YES,似乎使用我使用的库,当操作完成时,它不会立即执行成功 block ,而是将成功 block 与主队列进行dispatch_async。
所以正确发生的事情是:
1. 用户获取图像 -> 创建一个操作
2.操作完成->dispatch_async成功 block (仍然没有执行)
3. 在执行 success block 之前,用户 dealloc -> 取消他的所有操作(但不是步骤 1 中的操作,因为它处于 isFinished 状态)
4.现在成功 block 被执行->当尝试引用用户时我得到EXC_BAD_ACCESS。
还是不知道如何解决这个问题..
最佳答案
[[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
}
}
关于objective-c - Objective c - 取消 dealloc 中的操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11412587/