我正在使用一个在后台运行的库,然后调用一个完成处理程序。一切都很标准。
[[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中始终为null。如果我将其更改为__block
而不是__weak
,则weakOperation
是正确的实例,但其isCancelled
状态始终为NO
。
我在正确的时间调用[self.queue cancelAllOperations];
,此时单元格已移出屏幕。
所以我的问题是,在将该单元格重新用于另一位艺术家后,如何防止successHandler运行?
答案 0 :(得分:2)
问题在于您正在调用异步API。操作的生命周期是对getInfoForArtist:successHandler:
的调用,可能会立即返回。在执行异步回调时,操作已被处理掉,这就是回调块内引用为零的原因。
当successHandler执行时,取消操作没有意义 - 你不会节省网络资源,你也可以在本地保存查找结果。 UI问题是您不应直接引用单元格(或其子视图,如果您重复使用它们)。您可以考虑将结果存储在键入行的NSDictionary
或艺术家ID的本地NSIndexPath
中。然后,在cellForRowAtIndexPath:
中,首先在进行LastFM调用之前检查该字典。在successHandler回调中,您可以遍历tableView的visibleCells
并尝试从字典中加载数据。