Как загрузить таблицу с каким-либо изображением по умолчанию, пока она не получит исходное изображение с интернет-iPhone? - PullRequest
0 голосов
/ 14 июля 2011

У меня есть uitableview, который хранит одно изображение в одной ячейке. Его изображение загружается из интернета. Проблема в том, что приложение работает медленно, пока его изображение не загружается из Интернета. Поэтому я хочу добавить механизм, чтобы он сначала загружался с изображением по умолчанию, а когда он получит оригинал, то изображение по умолчанию будет заменено исходным.

Дайте мне любой учебник или пример кода для него.

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 14 июля 2011

Получите ваше изображение через какой-то другой поток .... и используйте уведомление или делегат для отслеживания любых изменений в загрузке изображения ... предположим, что вы используете уведомление .... затем в классе, который вы указали в качестве наблюдателя для этогоуведомление перезагружает данные tableView .... чтобы изображение вашей таблицы обновлялось там, где было изображение по умолчанию .... для более подробной информации, давайте возьмем пример ..... Создайте класс операции для загрузки изображения, которое мы называембольшой палец .... В этом примере я делаю 2 класса 1. PhotoGalleryVC, который показывает список больших пальцев и некоторые детали каждого большого пальца и 2. LoadGalleryThumbOp [Op = operation] загружает большие пальцы и публикует уведомление, когда все готово

@protocol LoadGalleryThumbDelegate;
@interface LoadGalleryThumbOp : NSObject{

    NSIndexPath* indexPathInTableView;
    id <LoadGalleryThumbDelegate> delegate;
    NSMutableData *activeDownload;
        NSURLConnection *imageConnection;
    NSString * documentPath;
    BOOL imageDownload;
}
@property (nonatomic, assign) NSIndexPath* indexPathInTableView;
@property (nonatomic, retain) NSMutableData *activeDownload;
@property (nonatomic, retain) NSURLConnection *imageConnection;
@property (nonatomic, assign) id <LoadGalleryThumbDelegate> delegate;
@property (nonatomic, retain) NSString * documentPath;
@property (nonatomic) BOOL imageDownload;
- (void)startDownload;
- (void)cancelDownload;
- (void) persistData:(NSData*) data;
@end

@protocol LoadGalleryThumbDelegate 

- (void)appImageDidLoad:(NSIndexPath *)indexPath;

@end

в LoadGalleryThumbOp.m сделайте это как

@implementation LoadGalleryThumbOp

@synthesize year;
@synthesize indexPathInTableView;
@synthesize delegate;
@synthesize activeDownload;
@synthesize imageConnection,documentPath,imageDownload;

#pragma mark

- (void)startDownload
{
    self.imageDownload = YES;
    self.activeDownload = [NSMutableData data];
    NSFileManager* fm = [NSFileManager defaultManager];
    NSString* galleryDocumentPath = [self.documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"images/thumb.jpg"]];
    if ([fm fileExistsAtPath:galleryDocumentPath]) 
    {
        UIImage *image = [[UIImage alloc] initWithContentsOfFile:galleryDocumentPath ];
         self.gallery.thumpImage = image;
        self.activeDownload = nil;
        [image release];
        self.imageConnection = nil;
         [delegate appImageDidLoad:self.indexPathInTableView];
    }
    else {
        NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
                                 [NSURLRequest requestWithURL:
                              [NSURL URLWithString:#error yourImageUrl]] delegate:self];
        self.imageConnection = conn;
        [conn release];
    }
}

- (void)cancelDownload
{
    [self.imageConnection cancel];
    self.imageConnection = nil;
    self.activeDownload = nil;
}


#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.activeDownload appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    self.activeDownload = nil;
    self.imageConnection = nil;
    self.imageDownload = NO;
     [NSString stringWithFormat:@"images/thumb.jpg"]];
    [delegate appImageDidLoad:self.indexPathInTableView];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self persistData:self.activeDownload];    
    self.activeDownload = nil;
    self.imageConnection = nil;
    [delegate appImageDidLoad:self.indexPathInTableView];
}
- (void) persistData:(NSData*) data
{
    NSFileManager* fm = [NSFileManager defaultManager];
    NSString* galleryDocumentPath = [self.documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"images/thumb.jpg"]];
    if ([[NSFileManager defaultManager] fileExistsAtPath:galleryDocumentPath]) 
    {
        NSError* err = nil;
        [fm removeItemAtPath:galleryDocumentPath error:&err];
        if (err)
            NSLog(@"%s:%@",__FUNCTION__,err);
    }
    [fm createFileAtPath:galleryDocumentPath contents:data attributes:nil];
}

, этот класс загрузит желаемое изображение и вызовет его делегата, когда оно будет загружено. Теперь его использование используется в PhotoGalleryVC используйте это следующим образом

@interface PhotoGalleryVC : UIViewController <LoadGalleryThumbDelegate>{

    IBOutlet UITableView* albumListTableView;
    NSMutableDictionary *imageDownloadsInProgress;
    NSArray* allThumbs;
}
@property (nonatomic, retain) NSMutableDictionary *imageDownloadsInProgress;

- (void)appImageDidLoad:(NSIndexPath *)indexPath;
@end

в части .m

- (void)viewDidLoad {
     self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
     .....

}

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

NSFileManager* fm = [NSFileManager defaultManager];
    NSString* galleryDocumentPath =  [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"Gallery/%@/images/thumb.jpg",[someObj.title stringByReplacingOccurrencesOfString:@" " withString:@"_" ]]];
//this above line is just make a seperate folder for each object and store thumbs of that object in that folder ... so make it unique some how
    if (![fm fileExistsAtPath:galleryDocumentPath]) 
    {
        LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];
        if (galleryThumbDownloader != nil && galleryThumbDownloader.imageDownload == NO)
        {
            [cell.activityIndicator stopAnimating];
            cell.albumCoverImageView.image = [UIImage imageNamed:@"no_thumb.png"];
        }
        else {
            [cell.activityIndicator startAnimating];                
        }
        [self startIconDownload:temp forIndexPath:indexPath andYear:[NSString stringWithFormat:@"%d",selectedYear]];
    }
    else
    {
        [cell.activityIndicator stopAnimating];
        cell.albumCoverImageView.image = [UIImage imageWithContentsOfFile:galleryDocumentPath];
    }
    return cell ;
}

//The following method see if there is already so downloader that is downloading same image then it simply do nothing else it create a downloader and start it     
- (void)startIconDownload:(Gallery *)gallery forIndexPath:(NSIndexPath *)indexPath  andYear:(NSString*)yr
{
    LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];
    if (galleryThumbDownloader == nil) 
    {
        NSString* documentsPath =    [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString* nameWithoutSpace = [gallery.title stringByReplacingOccurrencesOfString:@" " withString:@"_" ];
        NSString* galleryDocumentPath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"Gallery//%@",nameWithoutSpace]];

        galleryThumbDownloader = [[LoadGalleryThumbOp alloc] init];
        galleryThumbDownloader.documentPath = galleryDocumentPath;
        galleryThumbDownloader.indexPathInTableView = indexPath;
        galleryThumbDownloader.delegate = self;
        [imageDownloadsInProgress setObject:galleryThumbDownloader forKey:indexPath];
        [galleryThumbDownloader startDownload];
        [galleryThumbDownloader release];   
    }
    else if(galleryThumbDownloader.imageDownload == NO)
    {
        if (albumListTableView.dragging || albumListTableView.decelerating) {
            [galleryThumbDownloader startDownload];
        }
    }
}

наконец метод, который вызывается при загрузке определенного изображения

- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
    CustomCellPhotoGalary* cell = (CustomCellPhotoGalary*)[albumListTableView cellForRowAtIndexPath:indexPath];
    LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];

    if (galleryThumbDownloader != nil)
    {
        if (galleryThumbDownloader.imageDownload) 
        {
            [cell.activityIndicator stopAnimating];
            NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];                                
                    NSString* nameWithoutSpace = [temp.title stringByReplacingOccurrencesOfString:@" " withString:@"_" ];
            NSString* galleryDocumentPath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"Gallery/%@",nameWithoutSpace]];
            cell.albumCoverImageView.image = [UIImage imageWithContentsOfFile:galleryDocumentPath];
            //galleryThumbDownloader = nil;
        }
        else {
            [cell.activityIndicator stopAnimating];
            cell.albumCoverImageView.image = [UIImage imageNamed:@"no_thumb.png"];
            [self startIconDownload:temp forIndexPath:indexPath andYear:[NSString stringWithFormat:@"%d",selectedYear]];
    }
        [albumListTableView reloadData];
    }
}

woooh .....!Это много кода для одного примера. Примечание: я вырезал так много строк, чтобы этот код не работал для вас напрямую {может быть так много ошибок ..}, но я надеюсь, что вы поняли основную идею за кулисами ...:)

0 голосов
/ 26 июля 2011

Согласно приведенному выше сценарию, всегда лучше использовать LazyTableImages.

Лучший пример приведен здесь

0 голосов
/ 14 июля 2011

Этот пример кода великолепен, он многому меня научил. При этом используется инфраструктура ASIHttpRequest. Если вы собираетесь использовать эту технику, я рекомендую использовать самую последнюю версию из здесь , потому что версия в примере кода сейчас довольно старая.

Этот пример кода должен помочь вам с пользовательским делегированием ваших ячеек и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...