1

さまざまな時点で進行状況バーを表示し、終了したら非表示にする UITableView があります。ただし、プログレス バーは消えるはずのときに消えません。

バックグラウンド

私が取り組んでいるアプリは、ユーザーがマルチメディアを多用するプロジェクトを作成できるように設計されています。ビューの 1 つは、現在利用可能なすべてのオーディオ ファイルのリストを表示し、ユーザーが音楽ライブラリを含む多数のソースから追​​加のファイルをインポートするオプションも提供します。

詳細

音楽ライブラリからのインポートを処理するために、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

ご覧のとおり、セルはインポーターからの通知をリッスンして、進行状況バーを非表示/表示するタイミングを決定します。1 つの曲だけをインポートしようとする場合、大きな問題はありません (ただし、曲が終了してからプログレス バーが非表示になるまでにわずかな遅延があるようです)。ただし、複数の曲をキューに入れると、すべての曲が終了するまで進行状況バーがまったく消えません。さらに悪いことに、セルをビューの外にスクロールすると、セルが再利用されたときに別の曲のプログレス バーが表示されます。

NSLog ステートメントとデバッガーの両方を使用して通知システムをテストしましたが、正常に動作しています (「self.downloadProgressBar.hidden = YES;」セクションが適切なタイミングで呼び出されています) が、進行状況バーは表示されたままです。この時点で、私は完全にアイデアがありません。ありとあらゆる助けをいただければ幸いです。

前もって感謝します。

4

1 に答える 1

0

コードがメイン スレッドで実行されていることを確認してください。NSNotification はバックグラウンド スレッドに投稿できるため、UI を更新しないバックグラウンド スレッドでコードが実行されます。

于 2013-05-31T21:00:59.107 に答える