Ios 如何防止在UITableView中更新单元格?
我有一个UITableView,它正在播放来自Internet的音频剪辑。正在使用singleton助手播放音频剪辑。当用户点击单元格中的按钮时,音频片段开始播放,进度指示器显示播放了多少音频片段,这很有效。有了这个单件,我传入了一个更新进度块,它在播放单元格时更新单元格 但是,当我滚动浏览剪辑列表时,其他UITableViewCell的进度指示器将继续前进。我的猜测是,当我在Ios 如何防止在UITableView中更新单元格?,ios,objective-c,uitableview,audio,Ios,Objective C,Uitableview,Audio,我有一个UITableView,它正在播放来自Internet的音频剪辑。正在使用singleton助手播放音频剪辑。当用户点击单元格中的按钮时,音频片段开始播放,进度指示器显示播放了多少音频片段,这很有效。有了这个单件,我传入了一个更新进度块,它在播放单元格时更新单元格 但是,当我滚动浏览剪辑列表时,其他UITableViewCell的进度指示器将继续前进。我的猜测是,当我在cellforrowatinedexpath中调用dequeueReusableCellWithIdentifier时,
cellforrowatinedexpath
中调用dequeueReusableCellWithIdentifier
时,它返回当前由音频播放单例更新的单元格。我如何解决这个问题
EDIT:这里的主要问题是,在playButtonPressed
中播放声音后,我传入了一个进度块。我每0.5秒更新一次进度。换句话说,如果我在cellForRow或类似的东西中将进度设置为0,它将在0.5秒后返回到当前进度
[[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];
}
}];
假设您使用的是自定义的
UITableViewCell
子类,那么处理此问题的最佳方法可能是重写cell类中的prepareforeuse
。在这里,您可以隐藏进度指示器、将其完全删除、将其重置为零或应用程序中最有意义的任何内容:
override func prepareForReuse() {
super.prepareForReuse()
progressView.progress = 0 // Or otherwise reset the progress view
}
prepareforeuse
被调用——顾名思义——就在将单元格从重用队列中取出以再次使用之前。您可以使用它将单元格恢复到一种状态,在这种状态下,可能已对特定索引路径执行的任何设置都会被重置
或者,根据您的设置,在退出队列时只查看每个单元格可能更有意义,并根据它是否是当前表示音频助手正在播放的剪辑的单元格来重置进度指示器
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
}
}
编辑:
添加到问题中的更新块的问题在于,您正在捕获该块中的特定单元格,但该单元格随后会在表中的其他位置被重用。相反,您需要使用indepath
从块内部获取单元格,因此它总是获取正确的单元格。例如:
[[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];
}
}];
在每个区块内执行此操作有点麻烦,但这是必要的。您可以通过定义便利属性使其稍微整洁:
@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
假设您使用的是自定义的UITableViewCell
子类,最好的处理方法可能是重写cell类中的prepareforeuse
。在这里,您可以隐藏进度指示器、将其完全删除、将其重置为零或应用程序中最有意义的任何内容:
override func prepareForReuse() {
super.prepareForReuse()
progressView.progress = 0 // Or otherwise reset the progress view
}
prepareforeuse
被调用——顾名思义——就在将单元格从重用队列中取出以再次使用之前。您可以使用它将单元格恢复到一种状态,在这种状态下,可能已对特定索引路径执行的任何设置都会被重置
或者,根据您的设置,在退出队列时只查看每个单元格可能更有意义,并根据它是否是当前表示音频助手正在播放的剪辑的单元格来重置进度指示器
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
}
}
编辑:
添加到问题中的更新块的问题在于,您正在捕获该块中的特定单元格,但该单元格随后会在表中的其他位置被重用。相反,您需要使用indepath
从块内部获取单元格,因此它总是获取正确的单元格。例如:
[[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];
}
}];
在每个区块内执行此操作有点麻烦,但这是必要的。您可以通过定义便利属性使其稍微整洁:
@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
就可以了,这是因为UITableView重用了tableViewCells,并且可以根据单元格的可用性为多个索引路径调用一个单元格。有几种方法可以解决此问题
cellForRowAtIndexPath
中重置进度和单元格UI这是因为UITableView重复使用tableViewCells,根据单元格的可用性,可以为多个IndExpath调用一个单元格。有几种方法可以解决此问题
cellForRowAtIndexPath
中重置进度和单元格UI在awakeFromNib中,您是对的……如何设置或隐藏进度。请确保在每次在
CellForRowatineIndexPath中设置进度值之前设置进度值nil
,这对我有效。这不起作用。请参阅编辑您是对的,在awakeFromNib中…如何设置或隐藏进度。请确保在每次在单元格中设置进度值之前设置进度值nil
,这对我有效。这不起作用。请参阅editThis,这不起作用,因为我正在传递在计时器上运行的更新块。请参阅编辑。这不起作用,因为我正在传递在计时器上运行的更新块。请参阅编辑。这不起作用,因为我正在传递在计时器上运行的更新块。请参阅编辑。好的,您正在捕获单元格实例,因此在滚动之后,它正在更新错误的单元格。查看我的编辑。这不起作用,因为我正在传递一个在计时器上运行的更新块。请参见编辑。好的,您正在捕获单元格实例,因此