1

我有一个细胞重用问题。

我所有的细胞都是一样的,只有一个部分。单元格包括标签、按钮和进度条。

该按钮触发声音(这是一个简单的“播放”按钮)。当调用 AVAudioPlayers 委托方法时audioPlayerDidFinishPlaying:,我取消了NSTimer更新进度条的方法,隐藏了进度条,也取消了音频播放器。

所有这一切都发生在我的单元格的类中,该类继承自UITableViewCell.

一切都像它应该的那样工作,除了一件事:

在播放声音时滚动会在新单元格上显示相同的进度条。

因此,如果我点击第二个单元格,滚动时显示的第二个下一个单元格将有一个向前移动的进度条(并在声音结束时停止+隐藏)。

我将向您展示我的自定义单元完整课程,希望这会有所帮助。我真的不知道如何解决这个问题。我尝试了 if 语句,cellForRow:但没有任何真正的成功。

@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是一个包含文件 URL 的数组

- (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;

}

我能做到的最好的办法是在进度条看不见时隐藏它,因此也不会显示其他进度条,但是重新滚动到我的播放单元格时会发出没有进度条的声音,这是不令人满意/不好的用户体验行为。

4

3 回答 3

4

确保在 中初始化单元格的所有属性cellForRowAtIndexPath:
由于您的细胞正在回收利用,它们将保留其现有属性。

于 2015-05-26T08:58:54.487 回答
2

The problem is you're reusing your audioplayer and surrounding logic. You need something external to check whether the cell in question is the one playing the sound and you need to move the controller logic into the controller.

Add this property to your view controller...

@property (nonatomic) NSString *playingFilename;

Move - (IBAction)playSound:(id)sender into the view controller and set the string when you select a specific button...

- (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]];
}

then

- (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;
}
于 2015-05-26T11:07:42.080 回答
0

在行方法的表格视图单元格中,检查是否选择了行,如果没有选择,则将进度条的进度设置为零。

于 2015-05-26T09:16:11.920 回答