2

テーブルビューにカメラロールから画像を取り込もうとしています。

ViewDidLoad、アセット グループを作成します。

- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;

self.assetsLibrary = [[ALAssetsLibrary alloc] init];
[self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    if(nil!=group){
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];
        self.assetGroup = group;
        NSLog(@"%d images found", self.assetGroup.numberOfAssets);
    }
} failureBlock:^(NSError *error) {
    NSLog(@"block fucked!");
}];
[self.tableView reloadData];

}

ではCellForRowAtIndexPath、GCD バックグラウンド キューを使用して、セルにそれぞれのインデックスの画像を入力します。

 static NSString *CellIdentifier = @"Cell";

    dispatch_queue_t imgLoadQueue = dispatch_queue_create("Thumb loader", NULL);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

}

dispatch_async(imgLoadQueue, ^{
    [self.assetGroup enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:indexPath.row] options:0 usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
        if (nil != result) {
            ALAssetRepresentation *repr = [result defaultRepresentation];
            UIImage *img = [UIImage imageWithCGImage:[repr fullResolutionImage]];
            cell.imageView.image = img;

        }
    }];

});


return cell;

問題は、最初のセルが空であることです。スクロールを開始した後にのみ、画像の読み込みが開始されます。それも、スクロールするとすぐにアプリがクラッシュします。私はGCDにかなり慣れていないので、正しく使用していないようです。この問題の助けをいただければ幸いです。

4

2 に答える 2

2

cellforRowAtIndexPath メソッドの行を次のように変更します。

cell.imageView.image = img;

に:

dispatch_async(dispatch_get_main_queue(), ^{
    cell.imageView.image = img;
});

ビューのすべての変更は、メイン スレッドで実装する必要があります。他のスレッドでセル イメージを変更した場合 (現在行っていること)、セルの表示は変更されません。

于 2013-06-01T14:06:50.110 に答える
2

[self.tableView reloadData]の列挙ブロックviewDidLoadが完了してデータが入力された後に呼び出す必要がありますself.assetGroup。列挙ブロックは非同期で実行されるため、ブロックが完了する前に reloadData が呼び出され、テーブル ビュー デリゲート コールバックでは、assetGroup にデータが含まれていません。スクロールを開始するまでに、プロパティが設定され、画像が表示され始めます。

列挙ブロックの終わりを検出する方法を説明するアップルのドキュメントは見たことがありませんが、これら2つの受け入れられた回答は、列挙が終了するとグループ値がnilになることを示しています。

iPhone enumerateGroupsWithTypes 終了セレクター 非同期呼び出しがいつ終了したかを調べる

だからあなたのグループ列挙ブロックにelse条件を入れてください -

 if(nil!=group){
    [group setAssetsFilter:[ALAssetsFilter allPhotos]];
    self.assetGroup = group;
    NSLog(@"%d images found", self.assetGroup.numberOfAssets);
}
else
    [self.tableView reloadData];

列挙ブロックの後に呼び出されている reloadData を削除します。

CellForRowAtIndexPath の列挙ブロックを GCD キューから取り出してみてください。そのブロックも非同期で実行されます。バックグラウンド キューにディスパッチする必要はありません。

于 2013-06-01T15:38:35.273 に答える