ios - 在启动异步请求后如何保留对 UICollectionViewCell 的引用?

标签 ios objective-c asynchronous uicollectionview

我有一个由子类 UICollectionViewCell 组成的 UICollectionView。

这些单元格上有按钮,可以向 API 发出异步请求。在一种情况下,我有一个“心脏”按钮。点击它会禁用按钮并异步调用 API 并传入一个 block 以用作回调。当调用成功返回时,按钮将更新为不同的状态。

问题是,当调用 block 中的代码时,对单元格的引用似乎丢失或更改。因此,不好的事情发生了,比如当单元格滚出屏幕时,按钮的状态永远不会更新,并且只要重新使用该单元格,按钮就会保持禁用状态。

此处的最佳做法是什么?

- (void)didTapHeart:(id)sender event:(id)event {
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.collectionView];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:currentTouchPosition];

__block MyObject *object = [myObjects objectAtIndex:indexPath.row];
__block CollectionViewCell *cell = (CollectionViewCell *)[sender superview];

cell.btnHeart.enabled = NO;

[[ApiSingleton defaultApi] like:object success:^{
    dispatch_async(dispatch_get_main_queue(), ^{
        cell.btnHeart.enabled = YES;
        object.isLiked = YES;
        object.likeCount++;
        [cell setLiked:YES];
    });

} failure:^(NSDictionary *error) {

    dispatch_async(dispatch_get_main_queue(), ^{
        [cell setLiked:NO];
        cell.btnHeart.enabled = YES;
        object.isLiked = NO;
    });
}];

最佳答案

不要保留对单元格的引用 - 保留对索引路径的引用,并在您关心的索引路径处向 Collection View 询问单元格 例如:

[[ApiSingleton defaultApi] like:object success:^{
    dispatch_async(dispatch_get_main_queue(), ^{
        CollectionViewCell *blockCell = [self.collectionView cellForItemAtIndexPath:indexPath];
        blockCell.btnHeart.enabled = YES;
        object.isLiked = YES;
        object.likeCount++;
        [blockCell setLiked:YES];
    });

} failure:^(NSDictionary *error) {

    dispatch_async(dispatch_get_main_queue(), ^{
        CollectionViewCell *blockCell = [self.collectionView cellForItemAtIndexPath:indexPath];
        [blockCell setLiked:NO];
        blockCell.btnHeart.enabled = YES;
        object.isLiked = NO;
    });
}];

因为在这种情况下 cellForItemAtIndexPath: 返回表示 object 的单元格,或者如果屏幕上不存在这样的单元格则返回 nil时间,您不仅更新 object,而且保证在回调发生时更新代表它的单元格,这样您就不会干扰其他单元格。您所看到的问题的根源是 Collection View 重复使用了单元格,因此在任何给定时间,单元格都可以代表完全不同的索引路径中的数据。

完全不相关,但您不需要将 object 设为 __block 变量,因为您永远不会更改变量本身的值。与 cell 相同,尽管在此更改之后您无论如何都不会在 block 中使用它。

关于ios - 在启动异步请求后如何保留对 UICollectionViewCell 的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19820378/

相关文章:

ios - CAShapeLayer渲染问题

objective-c - 带前导零的 NSDateFormater

jakarta-ee - @Asynchronous EJB 线程池配置

ios - 如何同步使用 AFNetworking 2.0 库?

ios - 将按钮从过滤后的图像重置为原始图像

ios - Flutter - Codemagic - 自定义方案的 iOS 代码签名问题

ios - 多任务处理时工具栏是动画的

ios - 在 IOS 中使用 NSPredicate 按数组的一个元素过滤数组的 NSArray

ios - 定期从服务器更新 blockerList.json

ios - 将完成 block 添加到 enumerateObjectsWithOptions