首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止在UITableView中更新单元格?

如何防止在UITableView中更新单元格?
EN

Stack Overflow用户
提问于 2015-08-14 18:13:14
回答 2查看 1.1K关注 0票数 1

我有一个UITableView正在播放一个来自互联网的音频剪辑。音频剪辑正在与一个单例助手一起播放。当用户点击单元格中的按钮时,音频剪辑就开始了,并且进度指示符显示已经播放了多少音频剪辑,这是可行的。使用这个单例,我传入一个更新进度块,它在播放时更新单元格。

但是,当我在剪辑列表中滚动时,进度指示符将继续用于其他UITableViewCells。我的猜测是,当我在cellForRowAtIndexPath中调用cellForRowAtIndexPath时,它将返回当前由播放单例音频更新的单元格。我怎样才能解决这个问题?

编辑:这里的主要问题是,在播放playButtonPressed中的声音之后,我正在传递一个进度块。我每0.5秒更新一次进度。换句话说,如果我在cellForRow中将进度设置为0或类似的东西,它将在0.5秒后返回到当前进度。

代码语言:javascript
复制
[[Singleton sharedInstance] playURL:url completionHandler:^{
    cell.playButton.selected = NO;
} errorHandler:^{
    cell.playButton.selected = NO;
} progressHandler:^(float progress) {
    if (cell.playButton.selected) {
        [cell.progressView setProgress:progress animated:YES];                
    }
}];
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-14 18:40:21

假设您使用的是自定义的UITableViewCell子类,那么处理这个问题的最好方法可能是重写单元格类中的prepareForReuse。在这里,您可以隐藏进度指示符,将其全部删除,将其重置为零或应用程序中最有意义的任何内容:

代码语言:javascript
复制
override func prepareForReuse() {
    super.prepareForReuse()
    progressView.progress = 0   // Or otherwise reset the progress view
}

prepareForReuse被调用-顾名思义,在从重用队列中取出单元之前,- just将再次使用。您可以使用它将您的单元格重新置于为特定索引路径执行的任何设置都会被重置的状态。

或者,根据您的设置,可能更有意义的是,在每个单元格退出队列时只查看它,并根据它是否是当前表示音频助手播放的剪辑的单元格来重置进度指示符。

代码语言:javascript
复制
func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MyCell
    if indexPath.row == audioPlayer.indexOfTrackBeingPlayed {
        cell.progressView.progress = audioPlayer.currentProgress
    } else {
        cell.progressView.progress = 0
    }
}

编辑:

添加到问题中的update块的问题是,您正在捕获该块中的特定单元格,但是该单元格随后会在表的其他位置被重用。相反,您需要使用indexPath从块内部获取单元格,因此它总是得到正确的单元格。例如:

代码语言:javascript
复制
[[Singleton sharedInstance] playURL:url completionHandler:^{
    MyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    cell.playButton.selected = NO;
} errorHandler:^{
    MyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    cell.playButton.selected = NO;
} progressHandler:^(float progress) {
    MyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
    if (cell.playButton.selected) {
        [cell.progressView setProgress:progress animated:YES];                
    }
}];

必须在每个块内这样做有点麻烦,但这是必要的。通过定义一个方便的属性,您可以使它更加整洁:

代码语言:javascript
复制
@property(nonatomic, readonly) MyCell *playingCell;

- (MyCell *)playingCell {
    NSIndexPath *playingIndexPath = // get the index path of the playing item
    return [self.tableView cellForRowAtIndexPath:playingIndexPath];
}

然后将块中的cell替换为self.playingCell

票数 0
EN

Stack Overflow用户

发布于 2015-08-14 18:45:06

之所以会发生这种情况,是因为UITableView重用tableViewCells,可以根据单元的可用性为多个indexPaths调用一个单元。有几种方法可以解决这个问题

  1. 不要重复使用tableViewCell (不重复使用)
  2. cellForRowAtIndexPath中的重置进度和单元用户界面,
  3. 如果您有自定义单元格创建一个更新UI的方法,您也可以使用prepareForReuse方法,首先清除以前的UI,然后将其重置为新的UI。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32016323

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档