【问题标题】:Objective c - Canceling an operation in dealloc目标 c - 在 dealloc 中取消操作
【发布时间】:2012-07-10 11:42:56
【问题描述】:

我试图了解在操作的完成块中引用对象时,让对象在其 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 队列)NSOperation,该NSOperation 将及时启动NSURLConnection 以下载图像。当操作成功完成时,成功块将被调用。

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

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

    [super dealloc];
}

但似乎虽然我在dealloc方法中取消了操作,但有时在用户获得dealloc之后调用成功块,并且我在weakSelf.picture = downloadedImage行中得到EXC_BAD_ACCESS

为什么会这样?会不会是操作被取消了也试图完成连接?

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

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

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

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

【问题讨论】:

  • 请看我的更新
  • 是ARC项目吗(问是因为__block的语义在ARC下不一样),你的部署目标是5.0+吗?
  • weakSelf 需要在块的第一行使用,否则无效。解决方法是让它变得 strongSelf,例如“__strong typeof(self) strongSelf = weakSelf;”在第一行,然后你可以使用 strongSelf 之后。

标签: objective-c ios objective-c-blocks nsoperation


【解决方案1】:
[[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
       } 
     }

【讨论】:

  • 如果操作被取消,将不会调用成功块,所以我认为不需要。
  • 我查看了运行状态,是“isFinished”,怎么办??这很令人困惑:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-25
  • 2011-11-27
  • 1970-01-01
相关资源
最近更新 更多