2

私の- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath代理人は次のコードを持っています:

if ([movie isDownloaded])
    cell.detailTextLabel.text = movie.duration;
else
{
    cell.detailTextLabel.text = @"";

    [movie downloadInQueue:self.downloadQueue completion:^(BOOL success) {

        UITableViewCell *updateCell = [tblView cellForRowAtIndexPath:indexPath];            
        if (updateCell)
        {
            updateCell.detailTextLabel.text = movie.duration;
            [updateCell setNeedsLayout];
        }
    }];
}

Movie.m を呼び出して、次のコードを実行します。

- (void)downloadInQueue:(NSOperationQueue *)queue completion:(void (^)(BOOL success))completion
{
    if (!self.isDownloading)
    {
        self.downloading = YES;

        [queue addOperationWithBlock:^{
            BOOL success = NO;

            AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:self.fileURL];
            CMTime timeduration = playerItem.duration;
            float seconds = CMTimeGetSeconds(timeduration);
            self.duration = [self timeFormatted:seconds];

            self.downloading = NO;
            self.downloaded = YES;
            success = YES;

            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                completion(success);
            }];
        }];
    }
}

セルが表示されなくなったら、オブジェクトがまだ実行されていない場合NSOperationはオブジェクトをキャンセルします (キューから削除します)。MovieサブクラスUITableViewCell化して、次のようなことができることはわかっています。

- (void)willMoveToWindow:(UIWindow *)newWindow
{
    [super willMoveToWindow:newWindow];

    if (newWindow==nil) {
            // Cell is no longer in window so cancel from queue
    }
}

質問...デリゲート コールMovie NSOperation内でキャンセルするにはどうすればよいですか? UITableViewCellデリゲートと一緒NSNotificationですか、それとも何か?indexPath配列から正しい Movie オブジェクトを取得して操作をキャンセルするには、セルのを知る必要があります。

4

3 に答える 3

4

iOS 6以降、 UITableViewデリゲートプロトコルのtableView:didEndDisplayingCell:forRowAtIndexPath:メソッドを使用できます。これは、セルがテーブルビューから削除されたときに呼び出されます(セルが表示されなくなったときに発生します)。

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    // Cancel operation here for cell at indexPath
}
于 2013-01-20T22:58:55.593 に答える
2

ところで、私はこの質問をここで見ましたが、すでに答えましたここ. しかし、私はNebsに同意します(そして彼の答えは受け入れられるべきです)。

Nebs が言ったように、iOS 6 では、didEndDisplayingCell. したがって、次のようになります。

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    Movie *movie = self.movies[indexPath.row];

    if ([movie isDownloading])
        [movie cancelDownload];
}

しかし、以前のバージョンでは、 に応答したり、に含まれなくなったオブジェクトをscrollViewDidScroll手動で調べたり、そこから操作をキャンセルしたりする必要がありました。indexPathindexPathsForVisibleRows

操作をキャンセルするには、これを変更して、downloadInQueueを呼び出すだけでなく、addOperationWithBlockを作成してそれNSBlockOperationをキューに追加するだけでなく、参照も保存して、次のようにメソッドweakを記述できるようにする必要があります。cancelDownload

@interface Movie ()

@property (nonatomic, getter = isDownloaded) BOOL downloaded;
@property (nonatomic, getter = isDownloading) BOOL downloading;
@property (nonatomic, weak) NSOperation *operation;

@end

@implementation Movie

- (void)downloadInQueue:(NSOperationQueue *)queue completion:(void (^)(BOOL success))completion
{
    if (!self.isDownloading)
    {
        self.downloading = YES;

        NSOperation *currentOperation = [NSBlockOperation blockOperationWithBlock:^{
            BOOL success = NO;

            self.playerItem = [AVPlayerItem playerItemWithURL:self.webURL];
            if (self.playerItem)
            {
                success = YES;
                CMTime timeduration = self.playerItem.duration;
                float seconds = CMTimeGetSeconds(timeduration);
                self.durationText = [NSString stringWithFormat:@"%f", seconds];
            }
            self.downloading = NO;
            self.downloaded = YES;

            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                completion(success);
            }];
        }];

        [queue addOperation:currentOperation];
        self.operation = currentOperation;
    }
}

- (void)cancelDownload
{
    if ([self isDownloading] && self.operation)
    {
        self.downloading = NO;
        [self.operation cancel];
    }
}

@end
于 2013-01-20T23:53:32.113 に答える
0

セルまたはインデックスパスのいずれかをに渡す必要があるようですdownloadInQueue:completion:。次に、ディクショナリ、配列、または関連するオブジェクトを使用して、セルとその操作の間の接続を維持できます。

于 2013-01-20T23:01:48.037 に答える