Uislider в uitableviewcell больше не обновляется автоматически при прокрутке
У меня небольшие проблемы с моим кодом, и я надеялся получить здесь помощь
У меня есть uitableview, в каждую ячейку uitableview я помещаю индивидуальный uislider. Каждый uislider, используется как индикатор выполнения для воспроизведения музыки.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIButton *button = nil;
UISlider *customSlider = nil;
static NSString *CellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UIImage *image = [UIImage imageNamed:@"button_play.png"];
button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(340.0, 10.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:@selector(playAudio:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 4;
[cell.contentView addSubview:button];
customSlider = [[UISlider alloc] initWithFrame:CGRectMake(10, 45, 456, 20)];
customSlider.minimumValue = 0.0;
customSlider.maximumValue = 100.0;
customSlider.continuous = YES;
customSlider.tag = 3;
customSlider.value = 0.0;
[cell.contentView addSubview:customSlider];
}
else {
customSlider = (UISlider *)[cell.contentView viewWithTag:3];
button = (UIButton *)[cell.contentView viewWithTag:4];
}
return cell;
}
- (void) playAudio:(UIButton *)sender {
UIButton *button = (UIButton *)[sender superview];
UITableViewCell *currentCellTouched = (UITableViewCell *)[button superview];
UITableView *currentTable = (UITableView *)[currentCellTouched superview];
NSIndexPath *indexPath = [currentTable indexPathForCell:currentCellTouched];
//currentCellPlaying type of UITableViewCell and accessible from the rest classe
currentCellPlaying = currentCellTouched;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:NSLocalizedString([listFilesAudio objectAtIndex:indexPath.row], @"") ofType:@"mp3"]];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
player.delegate = self;
[player prepareToPlay];
[(UISlider *)[currentCellTouched.contentView viewWithTag:3] setMaximumValue:[player duration]];
[(UISlider *)[currentCellTouched.contentView viewWithTag:3] setValue:0.0];
NSTimer *sliderTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
[player play];
}
- (void)updateTime:(NSTimer *)timer {
[(UISlider *)[currentCellPlaying.contentView viewWithTag:3] setValue:player.currentTime];
}
Когда я запускаю одну игру, все в порядке, и индикатор выполнения обновляется.
Моя проблема в том, что, когда я прокручиваю вниз / вверх вид таблицы, и ячейка, в которой воспроизводится музыка, исчезает, как только мы возвращаемся к ячейке, воспроизводящей музыку, uislider возвращается к 0 и больше не обновляется... (NSLOG подтверждает, что мы все еще заходим в метод "updateTime")
Если у вас есть решение моей проблемы, я был бы очень рад прочитать его.
Заранее спасибо.
2 ответа
Ответ Otium не совсем правильный, но он идет в правильном направлении. Celle - это не все один и тот же объект, но (на самом деле вы реализовали его таким образом) ячейки, которые покидают видимую область путем прокрутки, повторно используются для отображения других, прокручивая в видимую область. Поэтому, когда ячейка, в которой воспроизводится музыка, снова становится видимой, внутри нее отображается еще один объект-слайдер, а не исходный. Кроме того currentCellPlaying
объект (возможно) больше не отображается или отображается как другая ячейка. Так что когда вы обновляете это viewWithTag:3
Вы (иногда) этого не увидите. Что вы должны сделать, это сохранить "indexCurrentPlaying" вместо ссылок на ячейки или ползунки. С этим индексом вы можете украсить ячейку в конце cellForRowAt
.... И вы можете обновить ползунок точно в ячейке этого индекса внутри updateTime
, Надеюсь, это поможет.
РЕДАКТИРОВАТЬ:
Некоторый не проверенный код, который должен работать (возможно, с некоторыми исправлениями, но я думаю, что он объясняет идею):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIButton *button = nil;
UISlider *customSlider = nil;
static NSString *CellIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UIImage *image = [UIImage imageNamed:@"button_play.png"];
button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(340.0, 10.0, image.size.width, image.size.height);
button.frame = frame;
[button setBackgroundImage:image forState:UIControlStateNormal];
[button addTarget:self action:@selector(playAudio:) forControlEvents:UIControlEventTouchUpInside];
button.tag = 4;
[cell.contentView addSubview:button];
customSlider = [[UISlider alloc] initWithFrame:CGRectMake(10, 45, 456, 20)];
customSlider.minimumValue = 0.0;
customSlider.maximumValue = 100.0;
customSlider.continuous = YES;
customSlider.tag = 3;
customSlider.value = 0.0;
[cell.contentView addSubview:customSlider];
}
else
{
customSlider = [cell viewWithTag:3];
}
if([indexPath isEqual:currentPlayingIndexPath])
{
currentPlayingSlider = customSlider;
[self updateTime];
}
else if(customSlider == currentPlayingSlider)
{
currentPlayingSlider = nil;
}
return cell;
}
- (void) playAudio
{
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:NSLocalizedString([listFilesAudio objectAtIndex:currentPlayingIndexPath.row], @"") ofType:@"mp3"]];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
player.delegate = self;
[player prepareToPlay];
NSTimer *sliderTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
[player play];
}
- (void)updateTime:(NSTimer *)timer
{
[currentPlayingSlider setValue:player.currentTime];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
currentPlayingIndexPath = indexPath;
currentPlayingSlider = [cellForRowAtIndexPath: currentPlayingIndexPath];
[self playAudio];
}
Будь осторожен с NSIndexPath isEqual
, Кажется, в разных версиях SDK разные ответы ( смотрите здесь) ... Так как вам нужна только строка, ее можно изменить на currentPlayingIndexPath.row == indexPath.row
UItableView использует съемные ячейки, поэтому все ваши ячейки в основном являются одним и тем же объектом. В методе cellForRowAtIndexPath вы должны снова установить ход ползунка.