2014-01-12 2 views
0

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

Edit с более подробно ...

Когда я иду играть «станцию» на моем приложении, я делаю запрос к серверу, который возвращает JSON для воспроизведения. Внутри этого JSON есть каждая песня, а также данные, включая URL обложки альбома. Когда пользователь переходит на «станцию», я хотел бы предварительно загрузить изображения для следующего URL-адреса обложки альбома в стеке или всех URL-адресов обложек альбомов во всём плейлисте.

В любом случае, я попытался загрузить следующую альбом искусства URL в UIImage в фоновом режиме, как temporaryAlbumArt и тогда, когда следующая песня играет просто albumArt = temporaryAlbumArt, а затем повторите настройки следующего песни альбома в темп процесса и так далее ..

Я пытался что-то вроде этого:

if (temporaryAlbumArt) { 
    albumArt = temporaryAlbumArt 
} else { 
    albumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:firstAlbumArtURL]]]; 
} 

temporaryAlbumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:nextAlbumArtURL]]]; 

Я думаю, мой вопрос, что это лучший метод:

  • загрузки изображения или нескольких изображений с URL (ы) в память
  • используя эти образы позже без времени задержки
+1

Конкретно. Что вы попробовали, это не сработало? – auspicious99

+0

Я согласен, в какой части вы боретесь конкретно? Алгоритм? Код? Некоторые разъяснения помогут нам вам помочь! ;) – nalyd88

+0

Я сделал некоторые обновления, я не уверен, что они полезны :( – stewart715

ответ

0

Эта библиотека делает то, что вам нужно: JMImageCache

Loop через ваши URL, загрузите их через JMImageCache и когда вы должны показать изображение библиотека будет получать сохраненное изображение, если он закончит загрузку.

//You can do this when you get the array of urls to download the images in the background 
for(NSURL *url in urls) { 
    [[JMImageCache sharedCache] imageForURL:url]; 
} 

//and then when you need an image: 
[imageView setImageWithURL:url placeholder:[UIImage imageNamed:@"placeholder.png"]]; 
+0

Это ** точно **, что я пытался сделать, кроме того, что я получил ting 'No visible @interface для 'JMImageCache' объявляет селектор 'imageForURL'' - он заставляет меня передавать все параметры, включая' completionBlock' и 'failureBlock'. Не уверен, почему я не могу просто загрузить изображение в кеш, не делая ничего с ним немедленно. – stewart715

+1

Я написал, что по памяти, если ему нужен блок завершения/отказа, вы можете просто передать nil этим. Или используйте блоки, чтобы отслеживать, сколько изображений закончило загрузку или не удалось (чтобы вы могли показать индикатор прогресса). – Vrasidas

+0

Итак, я получил это немного, но по какой-то причине он замораживает приложение и забивает основную очередь. Он должен работать в фоновом режиме, и даже когда я отправляю его в фоновом режиме, все равно происходит. – stewart715

0

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

Если вы хотите, чтобы приложение сохраняло все загруженные изображения локально, вы, возможно, в конечном итоге столкнетесь с проблемами пространства, но это может сделать. Вы можете использовать загруженное изображение, а затем сохранить его в каталоге кешей (а не документатор или Apple не сойдет с ума!). Когда песня приходит, просто сделайте быструю проверку изображения, и если ее не локальная загрузка. Песни занимают несколько минут, поэтому должно быть время, чтобы сделать все это в фоновом режиме.

#define GET_QUEUE dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

// while song is playing... 
dispatch_async(GET_QUEUE, ^{ 
    // On a separate thread look for the image locally in the cache and then 
    // download it if necessary 
}); 

Я не уверен, если это отвечает на ваш вопрос или нет ...

Ok так вот немного больше кода - в основном это позволяет мне спросить, надеюсь, полезные вопросы в контексте.

// Inside some loop/method that plays songs... 
if (temporaryAlbumArt) 
    albumArt = temporaryAlbumArt 
else 
    albumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:firstAlbumArtURL]]]; 
    // If this keeps executing then perhaps temporaryAlbumArt is getting released somehow? 
    // Are you persisting it correctly through each iteration/method call? 

// show art... 
// start music  

// Call art update 
dispatch_async(GET_QUEUE, ^{ 
    temporaryAlbumArt = nil; // In case the data hasn't been obtained yet on the next iteration??? 
    temporaryAlbumArt = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:nextAlbumArtURL]]]; 
    // This works ok then? Can you make sure this is completing correctly before the next iteration/method call? 
});  

Извините, но я не могу больше помочь.

+0

Именно то, что я пытался сделать, но мне интересно, какой лучший способ загрузки изображения в фоновом режиме а затем использовать то же изображение, когда вызывается следующий трек. Когда я делаю что-то вроде этого: 'UIImage * image = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: MyURL]]] ;; и затем использовать тот же UIImage для следующей песни он не работает, он снова загружает изображение. – stewart715

+0

Хм, ну, я думаю, нам нужен еще один код, чтобы посмотреть ... Похоже, вы вызываете метод, когда вам нужно я буду обновлять свой ответ немного больше информации, но потом я уйду спать на ночь! Удачи! – nalyd88

+0

Спасибо, не беспокойтесь. Я добавил несколько подробностей того, что я пробовал в своем вопросе – stewart715

1

Вы можете использовать это "должен иметь" инструмент APSmartStorage. Он поддерживает все, что вам нужно.

0

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

-(void)downloadImageForProductsFromArray:(NSArray *)inventoryArr { 
BOOL isAllDataDownloaded = YES; 
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 
hud.labelText = @"Data Sync..."; 
[[NSOperationQueue mainQueue] addObserver:self forKeyPath:@"operations" options:0 context:nil]; 
for (int i = 0; i < inventoryArr.count; i++) { 
    NSString *productUrlStr = [inventoryArr objectAtIndex:i]; 
    NSData *dirData = [CommonUtils fetchImageDataFromDirectoryWithImageName: productUrlStr];/*****Check whether Image data is already downloaded and saved in document directory*****/ 
    if (!dirData) { 
     isAllDataDownloaded = NO; 

     NSBlockOperation *downloadImgOpr = [[NSBlockOperation alloc] init]; 
     downloadImgOpr.queuePriority = NSOperationQueuePriorityVeryHigh; 
     downloadImgOpr.qualityOfService = NSQualityOfServiceUserInitiated; 

     [downloadImgOpr addExecutionBlock:^{ 
      NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString: productUrlStr]]; 
      if (imageData) { 

       /*****Save Image Data in Document Directory*****/ 
      } 
     }]; 

    } 
} 
if (isAllDataDownloaded) { 
    [MBProgressHUD hideAllHUDsForView:self.view animated:YES]; 
}} 

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
        change:(NSDictionary *)change context:(void *)context{ 
if (object == [NSOperationQueue mainQueue] && [keyPath isEqualToString:@"operations"]) { 
    if ([[NSOperationQueue mainQueue].operations count] == 0) { 
     // Do something here when your queue has completed 
     [MBProgressHUD hideAllHUDsForView:self.view animated:YES]; 

     NSLog(@"queue has completed"); 
    } 
} 
else { 
    [super observeValueForKeyPath:keyPath ofObject:object 
          change:change context:context]; 
} 

}

В этом коде я все URL строки в array.In инвентаризации для цикла я сделал несколько операций и добавили эти операции в очередь (я использовал основную очередь для проведения UI и синхронизировать данные. Сделайте свою очередь нужной). Также я добавил KVO в очередь для значений ключевой переменной «операции», так что если количество операций равно 0, мы можем сделать полезную операцию.

Смежные вопросы