1

我有一个 UITableView 应该在不同的时间显示进度条,然后在完成时隐藏它们。但是,进度条并没有在应该消失的时候消失。

背景

我正在开发的应用程序旨在允许用户创建多媒体项目。其中一个视图显示了当前可用的所有音频文件的列表,还为用户提供了从多个来源导入其他文件的选项,包括他们的音乐库。

细节

为了处理从音乐库的导入,我使用了 Chris Adamson 在他的博客中发布的代码的变。用户可以根据需要将尽可能多的导入排队,代码将自动按顺序导入它们。读/写部分在后台执行,并发出通知让应用程序的其余部分知道进程的状态。

用户可用的所有音频文件都显示在 UITableView 中。表格视图使用自定义单元格,其中包含一个标签(显示文件名)和一个进度条(除非歌曲处于中间导入状态,否则进度条始终隐藏)。

这是单元格的代码:

@interface AudioTableCell()

@property (nonatomic, strong) NSString *importingFileName;

@end


@implementation AudioTableCell


// ---------------------------------------------------------------------------------------------------------------------
- (void) prepareForReuse
{
    // remove notification listeners to avoid creating duplicates
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kNotifMusicLibMgrUpdateProgress object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kNotifMusicLibMgrFinishedImportingSong object:nil];

    // reset cell properties to default values
    self.isClickable = YES;
    self.downloadProgress.hidden = YES;
}


// ---------------------------------------------------------------------------------------------------------------------
// called by view controller prior to deleting a cell
- (void) prepareCellForDeletion
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kNotifMusicLibMgrUpdateProgress object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kNotifMusicLibMgrFinishedImportingSong object:nil];
}


// ---------------------------------------------------------------------------------------------------------------------
// called by the view controller's cellForRowAtIndexPath method
- (void) configureCell
{
    // by default, cell should be clickable and the progress bar should be hidden
    self.isClickable = YES;
    self.downloadProgress.hidden = YES;

    // listen to the import manager for updates on the import's progress
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(importWasUpdated:)
                                                 name:kNotifMusicLibMgrUpdateProgress
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(importWasFinished:)
                                                 name:kNotifMusicLibMgrFinishedImportingSong
                                               object:nil];

    // when the cell is scrolled out of view, the progress bar is hidden
    // need to remember if depicted song was in process of being downloaded
    if (self.importingFileName.length > 0) {
        if ([self.trackLabel.text isEqualToString:[self.importingFileName stringByAppendingPathExtension:@"m4a"]]) {
            self.downloadProgress.hidden = NO;
            self.isClickable = NO;
        }
    }
}


// ---------------------------------------------------------------------------------------------------------------------
// triggered when receiving a notification that a song has been imported successfully
- (void) importWasFinished:(NSNotification *)notification
{
    // the notification will pass the name of the song that was imported
    NSString *fileName = [notification.userInfo objectForKey:@"audioFileName"];

    // if the song that was imported matches the song being displayed by the cell, hide the progress bar
    // and make the cell clickable
    if ([self.trackLabel.text isEqualToString:[fileName stringByAppendingPathExtension:@"m4a"]]) {
        self.downloadProgress.hidden = YES;
        self.isClickable = YES;
    }

    // if the song that was imported matches the song that was "saved" by the cell, clear the saved song
    if ([self.importingFileName isEqualToString:fileName]) {
        self.importingFileName = @"";
    }
}


// ---------------------------------------------------------------------------------------------------------------------
// triggered when receiving a an update notification (currently 1/second)
- (void) importWasUpdated:(NSNotification *)notification
{
    // the notification will pass the name of the song being imported, its progress, and the number of songs queued
    NSString *fileName = [notification.userInfo objectForKey:@"audioFileName"];
    double completion = [[notification.userInfo objectForKey:@"progress"] doubleValue];

    // if the cell is displaying the song being imported, disable the cell and show a progress bar
    // also, store the name of the song - this way, if the cell is reused for a different song, it will still remember
    // the song being downloaded and can immediately display the progress bar when brought back into view
    if ([self.trackLabel.text isEqualToString:[fileName stringByAppendingPathExtension:@"m4a"]])
    {
        self.isClickable = NO;
        self.downloadProgress.hidden = NO;
        [self.downloadProgress setProgress:completion];
        self.importingFileName = fileName;
    } else {
        self.downloadProgress.hidden = YES;
        self.isClickable = YES;
    }
}


@end

如您所见,单元格侦听来自导入器的通知以确定何时隐藏/显示进度条。如果我只尝试导入一首歌曲,则不会出现重大问题(尽管歌曲完成时间和进度条隐藏时间之间似乎确实存在轻微延迟)。但是,如果我将多首歌曲排队,则进度条在所有歌曲完成之前都不会消失。更糟糕的是,将单元格滚动到视野之外会导致当单元格被重复使用时,进度条会出现一首不同的歌曲。

我已经使用 NSLog 语句和调试器测试了通知系统,它工作正常(“self.downloadProgressBar.hidden = YES;”部分在正确的时间被调用),但进度条仍然可见。在这一点上,我完全没有想法。任何和所有的帮助将不胜感激。

提前致谢。

4

1 回答 1

0

请检查您的代码是否在主线程上执行。NSNotification 可以发布在后台线程上,因此您的代码将在不会更新 UI 的后台线程上执行。

于 2013-05-31T21:00:59.107 回答