0

テキストと画像(右側の画像)が表示されたカスタムセルを含むUITableViewがあります。最初はすべて正常に機能していましたが、スクロールするとテーブルビュー全体が遅れていることに気付きました。これは、セルを再利用するときにセルが画面に入ったときに、アプリがセルの画像をダウンロードした可能性があるためです。ダウンロードした画像を保存するためにNSCacheを追加し、imageNameが存在する場合はロードするようにcellForRowAtIndexPathに指示しました。存在しない場合は、インターネットから再度ダウンロードします。ただし、キャッシュは非常に短期間のストレージであるため、ホームボタンを使用してアプリを終了し、再入力すると、一部の画像のみが残り、画像を再度ダウンロードする必要があります。

キャッシュよりも長期間画像を保存するための最良の方法を見つけようとしています。NSDirectoryとアプリライブラリへの保存について読んだことがありますが、まだ理解していません。

最も論理的な解決策は、次のようなことを行うことだと思います。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

     /*stuff*/

    NSString *imageName = [dictionary objectForKey:@"Image"];
    UIImage *image = [--Cache-directory-- objectForKey:imageName]; //Try to get it from cache

    if(image) //If image was received from cache:
    {
        cell.imageView.Image = image;
    }
    else //If not in cache:
    {
        image = [--local-directory-- objectForKey:imageName]; //Check some local directory

        if(image) //If image received from directory:
        {
            cell.imageView.Image = image;
            // + Also save it to the cache?
        }
        else //If image was in neither cache or local directory, get it from the website with given URL
        {
            image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];
            //Then save to cache and to file?
        }
    }


}

画像は頻繁に変更または切り替えられますが、事前にアプリに実装するつもりはないので、画像が追加されるたびに更新をリリースする必要があります。

これは私には論理的に思えるものです。私は正しい方向に進んでいますか?そして、どうすればローカルディレクトリを「呼び出す」ことができますか?たとえば、NSDirectoryオブジェクトなどに画像を追加すると、毎回リセットされませんか?ローカルフォルダにアクセスするにはどうすればよいですか?

4

4 に答える 4

3

間違った方向から問題を攻撃しています...
問題は、tableViewが遅れていることです。
その理由は、メインスレッドで画像をダウンロードするためです。
ディスクから画像を読み取っても、最高のスクロールパフォーマンスは得られません。

したがって、メインスレッドをブロックしてはなりません。これを行うには、画像を非同期でダウンロードするか、GCDを使用して別のスレッドでダウンロードします。

このような:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

     /*stuff*/  

     // this will block your main thread, bad idea..
     //image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];

     // instead call it in a separate thread  
     dispatch_queue_t imgDownloaderQueue = dispatch_queue_create("imageDownloader", NULL);
         dispatch_async(imgDownloaderQueue, ^{
         // download the image in separate thread
         UIImage *image = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]] autorelease];
         dispatch_queue_t main_queue = dispatch_get_main_queue();
         dispatch_sync(main_queue, ^{                        
            // this is called in the main thread after the download has finished, here u update the cell's imageView with the new image
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.imageView.image = image;
        });
    });
    dispatch_release(imgDownloaderQueue);
}
于 2012-07-17T21:33:48.860 に答える
2

これらすべての画像を保存する必要はありません。

URLから画像を取得する場合は、AsyncImageLoaderを使用してください

そのリンクを使用して、ASyncImageViewのhファイルとmファイルを取得し、プロジェクトに保存します。

これを行っている場所にhファイルをインポートします

#import 'AsyncImageView.h'

次に、次のコードを使用します

[[AsyncImageLoader sharedLoader] cancelLoadingURL:image.imageURL];

image.imageURL=[NSURL URLWithString:@"imageURL"];
于 2012-07-17T20:47:01.377 に答える
1

私は最近UITableViewに取り組んでいましたが、同様の問題がありました。私が使用した回避策の1つは、画像が小さく(あなたもそうだと思います)、一意の名前が付いていたため、アプリのローカルドキュメントフォルダーに保存し、コアデータを使用して画像の場所への参照を保持しました。その場所から画像を読み込みます。画像が変更された場合は、それらの画像を変更します。ただし、これは最も洗練された方法ではないかもしれません。ただの提案です。

ローカルアプリディレクトリへのアクセスに関しては、これを使用します

// INSTANCE METHOD - get the path and file name for the saved plist
- (NSString *)getFileLocation:(NSString *)location {
    // Get all available file system paths for the user
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    // Get the "Documents" directory path - it's the one and only on iPhone OS
    NSString *documentsPath = [paths objectAtIndex:0];

    // Specify the file name, appending it to documentsPath above
    NSString *savedFileName = [documentsPath stringByAppendingPathComponent:location];
    NSLog(@"File Location %@", location);
    // We're done
    return savedFileName;
}
于 2012-07-17T20:31:10.213 に答える
1

最善の解決策はCoreDataを使用することかもしれないようです。ただし、@ Anachidが提案したものとは異なり、以前と同じようにインターネットからロードして、コアデータディレクトリに配置することができます。新しい写真を出すには更新する必要があるので、ソリューションに入れるのではなく、インターネットをお勧めします。その後、必要に応じてそれらを使用できます。

于 2012-07-17T20:35:39.583 に答える