0

私のアプリでは、ユーザーがのタブの1つを押すと、UITabBarビューを読み込んでユーザーに表示するのに時間がかかりすぎるため、混乱する可能性があります(これは、のWebから画像を読み込むためですUITableView)。そこで、すべての画像の読み込みが完了する前に、マルチスレッドを使用してビューを表示することにしました。

私はこのコードを使用しています:

- (UITableViewCell *)tableView:(UITableView *)tableView
           cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[SetsCustomCell alloc] initWithFrame:CGRectZero];
    }
    // getting url
    NSURL* imgUrl = [[NSURL alloc]initWithString:[[mainArray objectAtIndex:
                       indexPath.row]valueForKey:@"imageURL"]];
    //put this url and current cell in the dictionary
    NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:
                    imgUrl,@"localUrl",cell,@"localCell", nil];
   // multithreading time (calling loadImageWithParams method)
    [self performSelectorInBackground:@selector(loadImageWithParams:)
                           withObject:params];
    return cell;
}
-(void)loadImageWithParams:(NSDictionary*)params {
    NSURL* url = [params objectForKey:@"localUrl"];
    cell = [params objectForKey:@"localCell"];
    UIImage* thumb = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
    NSDictionary* backParams = [NSDictionary dictionaryWithObjectsAndKeys: 
                   cell,@"localCell",thumb,@"thumb", nil];
    [self performSelectorOnMainThread:@selector(setImage:)
                        withObject:backParams waitUntilDone:YES];
}
-(void)setImage:(NSDictionary*)params{
    cell = [params objectForKey:@"localCell"];
    UIImage* thumb = [params objectForKey:@"thumb"];
    [cell.imageView setImage:thumb];
    cell.imageView.hidden = NO;
    [cell setNeedsLayout];
}

にセルが2つしかないUITableViewのですが、問題は2番目のセルだけがその画像をロードすることです。最初のセルはまだ空です。UITableViewただし、最初のセルが表示されなくなるまでスクロールしてcellForRowAtIndexPath:再度呼び出すと、最初のセルに画像が表示されます。

また、とを使用してマルチスレッドを作成しようとしましNSOperationQueueGCDが、同じ結果が得られました。

マルチスレッドがどのように機能するかを明確に理解していないようですが、誰かが私の間違いを指摘してくれたら、とても感謝しています。

ありがとう!

4

4 に答える 4

2

私が過去にこれを行った方法は、画像を格納するためのNSObjectサブクラスを作成することです。その場合、UITableViewのデータストアは、URLパスではなく、これらのオブジェクトの配列になります。

次に、このように画像を遅延ロードできます...

ObjectModel.h

@property (nonatomic, strong) UIImage *image;

ObjectModel.m

- (UIImage*)image
{
    if (_image == nil) {
        [self downloadImage];
        return [UIImage imageNamed:@"placeholderImage"];
    }
    return _image;
}

- (void)downloadImage
{
    //Put your async stuff here to download the image then reload the tableView when it's done.
}

これを行うことで、画像をデータストアに保存するだけでなく、ダウンロードを独自のクラスで管理し、TVCをクリーンに保つことができます。

于 2013-02-02T18:21:49.287 に答える
1

あなたはこれを過度に複雑にしているようです - 私はあなたが params 辞書で何をしているのか本当に理解していません. コントローラーを提示してから、viewDidAppear でダウンロードを開始してください。結果が戻ってきたら、それらを配列に入力し、reloadData を呼び出します。セルには、すぐに読み込める画像以外に何かありますか?

于 2013-02-02T18:24:56.847 に答える
1

これの典型的な方法は、バックグラウンドで画像をダウンロード/ロードする LazyUIImage クラスを実装することです。画像のダウンロード中に、UIActivityIndi​​cator のようなものを表示します。画像が LazyUIImage に到着したら、通知を送信し、アクティビティ インジケーターを停止します (おそらくビューから削除します)。LazyUIImage を含むすべてのビュー コントローラーに対して、その通知を処理し、[myTable reloadData] を実行します。LazyUIImage で、画像の読み込み中に nil を返し、画像の読み込み後に画像を返す getImage というメソッドを記述します。

編集: 実際には、LazyUIImage を LazyUIImageView として実装する場合、ビュー コントローラーを含むものをリロードする必要はありません。画像のダウンロードが完了しました。

于 2013-02-02T18:49:22.140 に答える
-2

遅延読み込みを行う必要があります。NSOperationQueue を使用して遅延読み込みを検索します。

于 2013-02-02T18:30:03.537 に答える