IPhone - загрузка асинхронной работы, но загрузка асинхронной не - PullRequest
0 голосов
/ 16 ноября 2011

Я создаю свою собственную ячейку для представления таблицы.Я пытаюсь загрузить изображение из Интернета, и для этого я использую асинхронную загрузку.Изображение загружается, но оно не отображается в моей ячейке.Я уже пытался показать в нормальном виде, и он работает нормально.Это также работает, если изображение уже загружено или я переворачиваю табличное представление и снова показываю ячейку.Кто-нибудь знает что происходит?

Код:

DownloadImageManager.m

-(id)initWithImageName:(NSString *)imageAddress{
    self = [super initWithFrame:CGRectMake(10, 5, 100, 100)];
    if (self){
        self.urlString = imageAddress;
        av = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
        av.frame = self.frame;
        [av setBackgroundColor:[UIColor greenColor]];
        [self addSubview:av];
        [av startAnimating];
        [self checkImage];
    }
    return self;
}

-(void)checkImage{
    bool isImageOnSysten = [self isImageOnFileSystem];
    if (isImageOnSysten) {
        //If image is on the system, loads the image, it's working fine here
        NSLog(@"CSantos: isImageOnSysten %@ is on system", self.urlString);
    } else {
        //here is the problem:
        [self downloadImage];
    }
}

-(void)downloadImage{
    NSURL *url = [NSURL URLWithString:self.urlString];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request setAllowCompressedResponse:YES];
    [request setQueuePriority:NSOperationQueuePriorityLow];
    [request setDidFinishSelector:@selector(requestFinished:)];
    [request setDidFailSelector:@selector(requestFailed:)];
    [request setTimeOutSeconds:25];
    [request setNumberOfTimesToRetryOnTimeout:3];

    [request startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSData *responseData = [request responseData]; 
    NSArray *words = [self.urlString componentsSeparatedByString:@"/"];
    NSString *fileName = [words lastObject];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
    NSError *error = nil;
    [responseData writeToFile:writablePath options:NSDataWritingAtomic error:&error];
    NSLog(@"Write returned error: %@", [error localizedDescription]);
    [av stopAnimating];
    [av removeFromSuperview];
}

CellForProgram.m

- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {

        textLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 31, 235, 40)] ;
        [self.contentView addSubview:textLabel];

        photo = [[UIImageView alloc] initWithFrame:CGRectMake(5, 5, 70, 70)];
        [photo setBackgroundColor:[UIColor blueColor]];
        photo.image = imagePhoto.image;
        [self.contentView addSubview:photo];
    }
    return self

Cell Caller

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

    static NSString *CellIdentifier = @"Cell";

    CellForProgram *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier] ;
    if (cell == nil) {
        cell = [[[CellForProgram alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }

    cell.textLabel.text = [speaker objectAtIndex:indexPath.row];

    DownloadImageManager *imageManager = [[DownloadImageManager alloc] initWithImageName:[images objectAtIndex:indexPath.row]];
    [cell.photo setImage:imageManager.image];
    return cell;
}

Ответы [ 2 ]

1 голос
/ 16 ноября 2011

Вы неправильно работаете с указателями.

Когда вы звоните [cell.photo setImage:imageManager.image];, а изображение не существует, вы указываете его на ноль или на случайную область памяти.

Вам необходимо создать указатель на вашу ячейку в классе DownloadImageManager, чтобы вы могли обновить ячейку после завершения загрузки изображения.

Вот что я рекомендую:

  • Создайте свойство в DownloadImageManager, которое указывает на ваш пользовательский класс UITableViewCell
  • Не устанавливайте изображение на tableView: cellForRowAtIndexPath: селектор. Вместо этого установите его непосредственно в DownloadImageManager.

Вот простая модификация вашего кода:

Cell Caller

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

    static NSString *CellIdentifier = @"Cell";

    CellForProgram *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier] ;
    if (cell == nil) {
        cell = [[[CellForProgram alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }

    cell.textLabel.text = [speaker objectAtIndex:indexPath.row];

    DownloadImageManager *imageManager = [[DownloadImageManager alloc] initWithImageName:[images objectAtIndex:indexPath.row] andCell:cell];
    return cell;
}

DownloadImageManager.m

-(id)initWithImageName:(NSString *)imageAddress andCell:(CellForProgram*)cell{
    self = [super initWithFrame:CGRectMake(10, 5, 100, 100)];
    if (self){
        self.urlString = imageAddress;
        self.cell = cell;
        av = [[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
        av.frame = self.frame;
        [av setBackgroundColor:[UIColor greenColor]];
        [self addSubview:av];
        [av startAnimating];
        [self checkImage];
    }
    return self;
}

-(void)checkImage{
    bool isImageOnSysten = [self isImageOnFileSystem];
    if (isImageOnSysten) {
        //If image is on the system, loads the image, it's working fine here
        NSLog(@"CSantos: isImageOnSysten %@ is on system", self.urlString);
        cell.photo = self.image;
    } else {
        //here is the problem:
        [self downloadImage];
    }
}

-(void)downloadImage{
    NSURL *url = [NSURL URLWithString:self.urlString];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request setAllowCompressedResponse:YES];
    [request setQueuePriority:NSOperationQueuePriorityLow];
    [request setDidFinishSelector:@selector(requestFinished:)];
    [request setDidFailSelector:@selector(requestFailed:)];
    [request setTimeOutSeconds:25];
    [request setNumberOfTimesToRetryOnTimeout:3];

    [request startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSData *responseData = [request responseData]; 
    NSArray *words = [self.urlString componentsSeparatedByString:@"/"];
    NSString *fileName = [words lastObject];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
    NSError *error = nil;
    [responseData writeToFile:writablePath options:NSDataWritingAtomic error:&error];
    NSLog(@"Write returned error: %@", [error localizedDescription]);
    [av stopAnimating];
    [av removeFromSuperview];

    cell.photo = self.image;
}

Это должно помочь вам. Если вам нужны какие-либо разъяснения, обязательно оставьте комментарий, и я скоро отвечу.

РЕДАКТИРОВАТЬ: В качестве альтернативы, реализовать метод делегата на DownloadImageManager ...

Добавьте это в DownloadImageManager.h:

@protocol DownloadImageManagerDelegate <NSObject>
@optional
- (void)DownloadFinished:(DownloadImageManager*)manager;
@end

Вместо CellForProgram используйте протокол DownloadImageManager с примером этого конструктора:

-(id)initWithImageName:(NSString *)imageAddress andDelegate:(DownloadImageManagerDelegate*)delegate

И измените вашу реализацию requestFinished: вот так:

- (void)requestFinished:(ASIHTTPRequest *)request
{
    NSData *responseData = [request responseData]; 
    NSArray *words = [self.urlString componentsSeparatedByString:@"/"];
    NSString *fileName = [words lastObject];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
    NSError *error = nil;
    [responseData writeToFile:writablePath options:NSDataWritingAtomic error:&error];
    NSLog(@"Write returned error: %@", [error localizedDescription]);
    [av stopAnimating];
    [av removeFromSuperview];

    if ([delegate respondsToSelector:@selector(DownloadFinished:)]) {
      [delegate DownloadFinished:self];
    }
}

Затем сделайте так, чтобы ваша клетка внедрила данный протокол, например:

- (void)DownloadFinished:(DownloadImageManager*)manager {
  this.photo = manager.image;
}

Таким образом, вы можете сохранять свои функциональные возможности в DownloadImageManager так, как хотите.

0 голосов
/ 18 ноября 2011

Я сказал, что мне не нужно вносить подобные изменения в DownloadImageManager!Но спасибо за попытку помочь, это помогло мне в других вещах, которые я застрял!

CellForProgram.m

- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {

        textLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 31, 235, 40)] ;
        [self.contentView addSubview:textLabel];

        imagePhoto = [[DownloadImageManager alloc] initWithImageName:imageAdress.text];
        [self.contentView addSubview:imagePhoto];
    }
    return self
}

DownLoadImageManager.m: добавить этот метод

-(void)changeImage:(NSString *)newImage{
    self.urlString = newImage;
    [self checkImage];
}

Cell Caller

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

    static NSString *CellIdentifier = @"Cell";

    CellForProgram *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier] ;
    if (cell == nil) {
        cell = [[[CellForProgram alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }

    cell.textLabel.text = [speaker objectAtIndex:indexPath.row];

    [cell.imagePhoto changeImage:[images objectAtIndex:indexPath.row]];
    return cell;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...