1

我正在使用一个在后台执行一些工作然后调用完成处理程序的库。一切都很标准。

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

我实际上在 tableview 中使用它:在每个单元格(子类)中,我获取有关艺术家的信息并显示它。这也是问题所在:当单元格被移出屏幕并为另一个艺术家重用时,前一个艺术家的成功处理程序仍然可以执行,导致标签和图像快速连续多次更改。

我的想法是创建一个 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 在单元格被另一位艺术家重用后运行?

4

1 回答 1

2

问题是您正在调用异步 API。操作的生命周期是对 的调用getInfoForArtist:successHandler:,它可能会立即返回。到异步回调执行的时候,操作已经被释放了,这就是为什么在回调块中引用为 nil 的原因。

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

于 2012-10-31T21:52:24.783 回答