我想了解在操作的完成块中引用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。
仍然不知道如何解决这个..
这是一个ARC项目? – 2012-07-10 17:53:26
请看看我的更新 – Eyal 2012-07-11 07:38:05
它是一个ARC项目(因为'__block'的语义在ARC下是不同的),并且您的部署目标是5.0+吗? – 2012-07-11 15:36:34