Асинхронная загрузка изображений iPad - PullRequest
0 голосов
/ 05 ноября 2011

Итак, у меня есть приложение, которое загружает и анализирует фид JSON с некоторыми URL-адресами. Каждый запрос загружает только 4 URL. Каждый URL является URL-адресом изображения, и я пытаюсь отобразить каждые четыре. Следующая кнопка будет отображать следующие четыре, оставляя предыдущие видимыми.

Когда я запускаю свое приложение, иногда оно работает, а иногда нет. Я получаю ошибку EXEC_BAD_ACCESS. Кроме того, я считаю, что это не самый лучший / самый эффективный способ загрузки изображений (даже если я делаю это асинхронно).

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

В моем ViewController у меня есть следующий метод:

- (void)imageSearchController:(id)searchController gotResults:(NSArray *)results {

    AsyncUIImage *imageDownload;

    for (int i = 0; i < [results count]; i++) {

        imageDownload = [[AsyncUIImage alloc] init];

        // Grab the image data in a dictionary
        NSDictionary *dictionary = [NSDictionary dictionaryWithDictionary:[results objectAtIndex:i]];        
        // Grab the values in an array
        NSArray *values = [NSArray arrayWithArray:[dictionary allValues]];
        // Get the image's URL in a string - strings at index 3
        NSString *url = [NSString stringWithString:[values objectAtIndex:3]];

        imageDownload.delegate = self;
        [imageDownload downloadImageFromURL:url];
        [imageDownload release];
    }
}

Этот метод - метод, который вызывается, как только канал JSON был загружен (используя NSURLConnection - это метод делегата). Он создает объект AsyncUIImage и затем передает URL каждого изображения этому объекту для загрузки и отображения.

Мой AsyncUIImage класс - это объект, который обрабатывает загрузку изображений. Он имеет следующие методы:

Сначала запустите загрузку следующим образом:

- (void)downloadImageFromURL:(NSString *)url {


    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
                                              cachePolicy:NSURLRequestUseProtocolCachePolicy
                                          timeoutInterval:60.0];

    // create the connection with the request
    // and start loading the data
    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {
        // Create the NSMutableData to hold the received data.
        // receivedData is an instance variable declared elsewhere.
        data = [[NSMutableData data] retain];
    } 

    else {
        NSLog(@"error in connection");
        [theConnection release];
    }
}

А затем обычные NSURLConnection методы делегирования. Метод connectionDidFinishLoading: выглядит следующим образом:

- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection {    
    self.image = [UIImage imageWithData:data];
    [self.delegate imageDidLoad:self.image];
}

Этот метод сообщает методу делегата, что изображение было загружено. Итак, вернемся к ViewController, этот метод делегата imageDidLoad отобразит изображения следующим образом:

- (void)imageDidLoad:(UIImage *)image {

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOffset, yOffset, 192, 192)];
    imageView.image = image;
    [imageView release];

    [self.view addSubview:imageView];
    xOffset = xOffset + 192;

    if (count != 0 && count % 4 == 0) {
        yOffset = yOffset + 192;
        xOffset = 0;
    }

    count++;
}

У меня нет большого опыта работы с асинхронными загрузками на платформе iOS, однако из опыта программирования и опыта iOS я считаю, что то, что я делаю, имеет некоторые серьезные недостатки.

У кого-нибудь есть идеи / предложения? Любая обратная связь высоко ценится.

Спасибо.

Ответы [ 2 ]

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

Возможно, это не тот ответ, который вы ищете, но я использовал эту библиотеку для этой цели: HJCache Я сделал клиентское приложение для твиттера, и моя собственная реализация загрузки асинхронных изображений тоже доставляла мне много проблем.

После изменения этой библиотеки все работало гладко, также вы можете изменить ее, если хотите добавить дополнительные функции или что-то еще.

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

1 голос
/ 05 ноября 2011
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(xOffset, yOffset, 192, 192)];
    imageView.image = image;
    [imageView release];

    [self.view addSubview:imageView];

К тому времени, когда вы передаете imageView в addSubview:, оно уже освобождено.Вам нужно выпустить после того, как вы добавите его в качестве подпредставления self.view.

Если вы Google управления памятью target-c , вы найдете множество руководств для начинающихчтобы помочь вам понять retain и release.

...