我有一个细胞重用问题。
我的所有细胞都相同,只有一个部分。单元格包括标签,按钮和进度条。
按钮触发声音(这是一个简单的“播放”按钮)。当调用AVAudioPlayers委托方法audioPlayerDidFinishPlaying:
时,我会使更新进度条的NSTimer
无效,隐藏进度条,并使音频播放器无效。
所有这些都发生在我的单元格类中,它继承自UITableViewCell
。
除了一件事之外,一切都像它应该的那样:
播放声音时滚动会在新细胞上显示相同的进度条。
因此,如果我点击第二个单元格,滚动时显示的第二个下一个单元格将向前移动一个进度条(并在声音结束时停止+隐藏)。
我会告诉你我的自定义单元格完整课程,我希望这会有所帮助。我真的不知道如何解决这个问题。我在cellForRow:
中尝试了if语句,但没有任何真正的成功。
@implementation SoundItemTableViewCell
- (void)awakeFromNib {
// Initialization code
self.progressBar.hidden = YES;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)playSound:(id)sender {
[self.progressBar setProgress:0];
self.progressBar.hidden = NO;
NSString *filename = self.fileName;
[self playSoundWithURL:[NSURL URLWithString:filename]];
}
- (void)playSoundWithURL:(NSURL*)url{
NSError *error;
if (self.audioPlayer){
if(self.audioPlayer.playing){
[self.audioPlayer stop];
}
}
self.audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
self.audioPlayer.delegate = self;
self.tmrProgress = [NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:@selector(updateElapsedTime) userInfo:nil repeats:YES];
[self.audioPlayer prepareToPlay];
[self.audioPlayer play];
NSLog(@"Starting sound play with item : %@",url);
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
[self.progressBar setProgress:0 animated:YES];
self.progressBar.hidden = YES;
//self.progressBar = nil;
[self.tmrProgress invalidate];
self.tmrProgress = nil;
player = nil;
self.audioPlayer = nil;
NSLog(@"Audio Finish");
}
- (void)updateElapsedTime{
if (self.audioPlayer) {
NSLog(@"Updating progress");
[self.progressBar setProgress:[self.audioPlayer currentTime] / [self.audioPlayer duration]];
}
}
桌面视图。 pushList
是一个包含文件网址的数组
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"SoundItemTableViewCell";
SoundItemTableViewCell *cell = [self.tbPushList dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[SoundItemTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.fileName = [pushList objectAtIndex:indexPath.row];
cell.lbName.text = [[[pushList objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
return cell;
}
我能做到的最好的方法就是在进度条出现时隐藏进度条,因此也没有其他进度条显示,但是重新进入我的播放单元然后会播放没有进度条的声音,这是不满意/不良的用户体验行为。
答案 0 :(得分:4)
确保在cellForRowAtIndexPath:
中初始化您单元格的所有属性
由于您的细胞正在被回收,它们将保留其现有的属性。
答案 1 :(得分:2)
问题是你正在重复使用你的音频层和周围的逻辑。你需要外部的东西来检查有问题的单元是否是播放声音的单元,你需要将控制器逻辑移动到控制器中。
将此属性添加到视图控制器...
@property (nonatomic) NSString *playingFilename;
将- (IBAction)playSound:(id)sender
移动到视图控制器中,并在选择特定按钮时设置字符串...
- (IBAction)playSound:(id)sender {
UIButton *playButton = sender;
NSInteger index = playButton.tag;
SoundItemTableViewCell *cell = (SoundItemTableViewCell *)[self.tbPushList cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
[cell.progressBar setProgress:0];
cell.progressBar.hidden = NO;
self.playingFilename = [pushList objectAtIndex:index];
// Personally I'd move the playing logic into the controller as well... spin up as many audio players as you need... but they shouldn't be in the cell.
[self playSoundWithURL:[NSURL URLWithString:self.playingFileName]];
}
然后
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"SoundItemTableViewCell";
SoundItemTableViewCell *cell = [self.tbPushList dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[SoundItemTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
// tag your button.....
cell.playButton.tag = indexPath.row;
cell.lbName.text = [[[pushList objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
// check to see if this index contains the right file
BOOL isRightFile = ([self.playingFilename isEqualToString:[pushList objectAtIndex:indexPath.row]])
cell.progressBar.hidden = !isRightFile;
return cell;
}
答案 2 :(得分:0)
在行方法的表格视图单元格中,检查是否选择了行,如果未选择该行,则将进度条的进度设置为零。