1

uicollectionview セルの画像の再描画に問題があります - 画像は JSON から解析された URL からダウンロードされます。10個のセルがあり、アプリの開始時に最初の6個のみが表示されますが、画像が読み込まれません。他のセルまでスクロールすると画像があり、上部にスクロールすると最初の4個のセルがあります画像も同様に、セル 5 と 6 のみが再描画されません (それらはずっと表示されていました)。これを長い間デバッグしようとしましたが、成功しませんでした。

cellForItemAtIndexPath で SDWebImage を呼び出しています (しかし、実際には問題ではありません):

[cell.backgroundImage setImageWithURL:[NSURL URLWithString:timeSnap.thumbnailImageURL]  placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

しかし、cellForItemAtIndexPath が初めて呼び出されたとき、timeSnap.thumbnailImageURL (timeSnap エンティティはセルのモデル) はまだ初期化されていないため、null です。

timeSnap.thumbnailImageURL の初期化後:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.collectionView reloadData];
});

edit1: コードを追加すると、少し複雑です。最初にサーバー API から JSON を取得し、アイテムをコレクション ビューに表示します。次に、アイテムごとにサーバー API から別の JSON を取得する必要があります。そこから URL を作成できます。 timeSnap.thumbnailImageURL

viewController クラス:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self refreshNewTimeSnapsFeed];
}

- (void)refreshNewTimeSnapsFeed {
    Adapter *adapter = [AppDelegate instance].adapter;

    [adapter getNewTimeSnapsWithCompletion:^(NSArray* jsonResponse) {
        [self newTimeSnapsFeedRefreshed:jsonResponse];
    }];
}

- (void)newTimeSnapsFeedRefreshed:(NSArray*)jsonResponse {
Adapter *adapter = [AppDelegate instance].adapter;

    for (NSDictionary *timeSnapDict in jsonResponse) {
        TimeSnap *timeSnap = [[TimeSnap alloc] initWithJSON:timeSnapDict];
        [adapter getTimeSnapSnapsforId:timeSnap.id withCompletion:^(NSArray*     jsonResponse) {
            [timeSnap getSnapsJSON:jsonResponse];
            [timeSnap getTimeSnapThumbnailImageURL];
        }];

        [self.timeSnaps addObject:timeSnap];
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.collectionView reloadData];
    });
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    TimeSnapCell *cell = (TimeSnapCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"TimeSnapCell" forIndexPath:indexPath];

    TimeSnap *timeSnap = self.timeSnaps[indexPath.row];

    cell.label.text = timeSnap.name;

    [cell.backgroundImage setImageWithURL:[NSURL URLWithString:timeSnap.thumbnailImageURL]  placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    return cell;
}

アダプタ クラス:

- (void)getNewTimeSnapsWithCompletion:(void (^)(NSArray* jsonResponse))completion {

    NSString *urlAsString = [NSString stringWithFormat:@"..."];
    NSURL *url = [[NSURL alloc] initWithString:urlAsString];

    [self getJSONWithCompletion:completion fromURL:url forKey:@"Items"];    
}

- (void)getTimeSnapSnapsforId:(NSNumber*)id withCompletion:(void (^)(NSArray* jsonResponse))completion {

    NSString *urlAsString = [NSString stringWithFormat:@"..."];
    NSURL *url = [[NSURL alloc] initWithString:urlAsString];

    [self getJSONWithCompletion:completion fromURL:url forKey:@"Items"];    
}

- (void)getJSONWithCompletion:(void (^)(NSArray* jsonResponse))completion fromURL:(NSURL*)url forKey:(NSString*)key {

    //code for getting JSON from server API, then parsing into NSArray *items

    dispatch_async(dispatch_get_main_queue(), ^{
        if(completion){
            completion(items);
        }
    });    
}
4

2 に答える 2

1

2 番目の JSON 応答が戻ってきたら、セルをリロードする必要があります。

for (NSDictionary *timeSnapDict in jsonResponse) {
    TimeSnap *timeSnap = [[TimeSnap alloc] initWithJSON:timeSnapDict];

    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.timeSnaps.count inSection:0];
    [self.timeSnaps addObject:timeSnap];
    [adapter getTimeSnapSnapsforId:timeSnap.id withCompletion:^(NSArray*     jsonResponse) {
        [timeSnap getSnapsJSON:jsonResponse];
        [timeSnap getTimeSnapThumbnailImageURL];
        [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
    }];
}

アダプター クラスはメイン キューで完了ブロックを実行するため、dispatch_asyncここで使用する必要はありません (アダプターのコントラクトのその部分を考慮しない場合を除きます)。

于 2013-11-09T16:39:39.383 に答える