2

我目前有一个设置,当网络进程完成时,点击一个单元会导致一个活动指示器出现在单元上。完成后,单元格会自动更新其 UI。

问题是,在这种情况下,如果用户将单元格滚动到当前被重用的屏幕上,并且当您向后滚动时,单元格要么在预先点击的 UI 中,要么在点击后的 UI 中(取决于是否处理在用户被滚动离开时完成)。

这使得正在执行的后台操作在用户看来似乎只是随机停止,但它仍在发生,只是 UI 被刷新。

因此,我正在努力解决如何暂时阻止单元格的重用,或者有什么办法可以在重用后在单元格(并且仅在该单元格上)保持一致的加载指示器?

编辑:用一些数据来保存而不是显示的想法indexPath是朝着正确方向迈出的一步,但顺序很可能,但不能保证保持不变。

所以我想问题就变成了:当我接到代表进程完成的调用时,我需要找到一些独特的东西来识别给定的单元格。我尝试使用标签的文本,因为它是“唯一的”(99% 的时间......)但这只能保证工作,除非我也传递“唯一”标识符(标签,甚至不能保证是独一无二的)通过我的支持课程进行有趣的过山车之旅,这样它就可以在最后使用。


我尝试过的事情

1) 尝试:通过在加载时将其放置在 NSMutableArray 属性中来保留单元格,并在完成后使用委托方法将其删除,即:

[self.loadingCells addObject:cell];

结果:没有效果


2) 尝试:向 UITableViewCell(我子类化)添加一个名为isLoading.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    if (cell.isLoading) {
        [cell.activityView startAnimating];
    }
}

结果:在正确的单元格上加载指示器,但在屏幕外时也会加载其他指示器。

工作得体,但我遇到了其他随机单元格现在神秘地看起来像是正在加载的问题,因为原始单元格被重复使用来制作它们。


3) 尝试:与尝试#1相同,除了使用(唯一)单元格的标签文本:

[self.loadingCells addObject:cell.label.text];

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    if ([self.loadingCells containsObject:cell.label.text]) {
        [cell.activityView startAnimating];
    }
}
// delegate method
- (void)finishedLoading:(MyCell *)cell {
    [cell.activityView stopAnimating];
    [self.loadingCells removeObject:cell.label.text];
}

结果:仅在正确的单元格上加载指示符,但如果在进程完成时单元格不在屏幕上,委托方法会尝试删除错误标签的文本,从而导致单元格看起来像是在永久加载。


4)然后我继续在委托方法上传递一个 NSString 并尝试比较它们并删除正确的字符串......这也给出了不可靠的结果。我认为这是因为传递给处理网络调用的类的单元格可能不会保持静态,如果我在调用提取标签文本时碰巧没有显示单元格,它会不正确。

所以我可以立即制作NSString并将其传递给我在不同课程中进行的精彩调用网络,但这太荒谬了,我已经不喜欢这个解决方案了......

4

1 回答 1

3

您不应该将此类数据存储在单元格上,我保证您绝对不想阻止单元格被重复使用。这是 UITableView 背后最强大的功能之一,也是它保持如此快速发展的原因。

处理此问题的最佳方法是使用数组或其他类型的数据存储来保存用于“配置”单元格的所有数据。本质上,有一个可以检查的数组cellForItemAtIndexPath来查看单元格是否需要指示器。然后根据此数据相应地配置单元格。这样,您实际上不需要在单元格中保留状态。

很难准确地安排这将如何完成,但这是一个非常人为的示例,说明如何使用地图检查单元格是否已加载。如果该单元格不在地图中,他们可以将其添加为默认值并照常进行处理。

//: Playground - noun: a place where people can play

import UIKit

let index1 = NSIndexPath(forRow: 0, inSection: 0)
let index2 = NSIndexPath(forRow: 1, inSection: 0)
let index3 = NSIndexPath(forRow: 2, inSection: 0)
let index4 = NSIndexPath(forRow: 3, inSection: 0)

var cellIsLoadingMap = [NSIndexPath: Bool]()
cellIsLoadingMap[index1] = true
cellIsLoadingMap[index2] = true
cellIsLoadingMap[index3] = false
cellIsLoadingMap[index4] = false

let index5 = NSIndexPath(forRow: 4, inSection: 0)

if let isLoading = cellIsLoadingMap[index5] {
    print(isLoading)
} else {
    cellIsLoadingMap[index5] = false
}
于 2015-11-13T03:33:52.817 回答