2012-10-26 41 views
1

我正在使用一个库,在后台执行一些工作,然后调用完成处理程序。所有非常标准。取消完成处理程序块运行

[[LastFm sharedInstance] getInfoForArtist:@"Pink Floyd" successHandler:^(NSDictionary *result) { 
    // Do stuff... 
} failureHandler:nil]; 

我实际上在tableview中使用这个:在每个单元格(子类)中,我得到关于艺术家的信息并显示它。这也是问题:当单元格被移出屏幕并重新用于其他艺术家时,前一个艺术家的successHandler仍然可以执行,从而导致标签和图像快速连续多次更改。

我的想法是创建一个NSOperationQueue,加上其内部的getInfoForArtist电话,并确保它可以被取消:

NSBlockOperation *operation = [[NSBlockOperation alloc] init]; 
__weak NSBlockOperation *weakOperation = operation; 

[operation addExecutionBlock:^{ 
    [[LastFm sharedInstance] getInfoForArtist:mediaItem.artist successHandler:^(NSDictionary *result) { 
     if (weakOperation.isCancelled) { 
      return; 
     } 
     // Do stuff... 
    } failureHandler:nil]; 
}]; 

[self.queue addOperation:operation]; 

的问题是,weakOperation总是successHandler内空。如果我将其更改为__block而不是__weak,则weakOperation是正确的实例,但其isCancelled状态始终为NO

我在正确的时间打电话给[self.queue cancelAllOperations];,当时单元格被移出屏幕。

所以我的问题是,如何防止在单元格被其他艺术家重用之后运行successHandler?

回答

2

问题是您正在调用异步API。您的操作的生命周期是致电getInfoForArtist:successHandler:,可能立即返回。在执行异步回调时,操作已被处理,这就是为什么引用在回调块内部为零的原因。

当执行successHandler时,取消操作没有意义 - 您不会节省网络资源,并且您也可以在本地保存查找结果。用户界面的问题是,你不应该直接引用单元格(或其子视图,如果你重用它们)。您可能会考虑将结果存储在本地NSDictionary中,该NSDictionary键位于该行的NSIndexPath或艺术家ID。然后,在您的cellForRowAtIndexPath:中,首先在进行LastFM调用之前检查该字典。在successHandler回调中,您可以遍历tableView的visibleCells并尝试从字典中加载数据。

相关问题