2016-02-11 16 views
5

Sto memorizzando circa 100 UIImage in un singolo array. So che c'è un problema di utilizzo della memoria che alla fine blocca l'app, in particolare sui dispositivi più vecchi (iPhone 4s). In termini di User Experience memorizzando tutti i UIImages su DocumentsDirectory - non è un'opzione (richiede troppo tempo). Quindi stavo pensando di "unire" questi due metodi. Attendi finché non ricevo un avviso sull'utilizzo della memoria, interrompi il salvataggio delle immagini sul mio array e quindi inizi a memorizzare sul disco. Non riesco a trovare il modo giusto per gestire Memory leak/warning/usage callProblema di memoria quando si lavora con array di UIImage di grandi dimensioni

override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     print("memory warning") 
    } 

Quando sto testando il dispositivo vero e proprio, è solo blocca - senza la chiamata del metodo. Eventuali suggerimenti?

+1

Penso che, se hai problemi di questo tipo, sia ridurre la qualità delle immagini o farle aspettare che l'app scriva sul disco. – brimstone

+0

Ehi, @GabrielJones. Sfortunatamente non posso. A causa delle mie esigenze, tutte dovrebbero esistere insieme. Non posso separare il gruppo in altre parole. –

+0

@GabrielJones, e in realtà ho ridotto la qualità di quasi il 60% (che è anche inferiore a quello che mi serve). Una buona domanda potrebbe essere, qual è il modo più efficace per ridimensionare un'immagine, in termini di qualità/byte –

risposta

1

Provare a utilizzare la libreria di immagini cache. Il confronto tra il più popolare è qui: https://bpoplauschi.wordpress.com/2014/03/21/ios-image-caching-sdwebimage-vs-fastimage/

La mia esperienza: SDWebImage è la migliore per le immagini URL di origine di solito da internet e Haneke è un bene per le immagini di identificazione basati ad esempio le miniature generate dal video. Entrambi disponibili in CocoaPods.

SDWebImage utilizza CoreData SQLite DB per la memorizzazione nella cache degli URL. Non ha metodi per immagini "a mano libera" ma è diffuso in tutto il mondo nelle applicazioni ~ REST che scaricano immagini da internet. Lo sto usando appena pubblicato nell'app AppHosters MyHairDressers. FastCache utilizza i file per la memorizzazione nella cache degli URL. Ma anche a SDWebImage non è adatto per memorizzare immagini "a mano" nella cache. Entrambi ben si adattano per le immagini scaricate dagli URL. Haneke può memorizzare immagini per ID personalizzati non solo da URL. Ma come FastCache richiede qualche configurazione. Ecco il codice per alcune configurazioni:

``

HNKCacheFormat *cacheFormatThumbnail = [[HNKCache sharedCache] formats][CACHE_FORMAT_THUMBNAIL]; 
     if (cacheFormatThumbnail == nil) 
     { 
      cacheFormatThumbnail = [[HNKCacheFormat alloc] initWithName:CACHE_FORMAT_THUMBNAIL]; 
      cacheFormatThumbnail.size = CGSizeMake(100.0f, 56.0f); 
      cacheFormatThumbnail.scaleMode = HNKScaleModeAspectFit; 
      cacheFormatThumbnail.compressionQuality = 0.5f; 
      cacheFormatThumbnail.diskCapacity = 10 * 1024 * 1024; // 10MB 
      cacheFormatThumbnail.preloadPolicy = HNKPreloadPolicyLastSession; 
      [[HNKCache sharedCache] registerFormat:cacheFormatThumbnail]; 
     } 
     HNKCacheFormat *cacheFormatPhoto = [[HNKCache sharedCache] formats][CACHE_FORMAT_PHOTO]; 
     if (cacheFormatPhoto == nil) 
     { 
      cacheFormatPhoto = [[HNKCacheFormat alloc] initWithName:CACHE_FORMAT_PHOTO]; 
      CGFloat scale = [[UIScreen mainScreen] scale]; 
      cacheFormatPhoto.size = CGSizeMake(1280.0f * scale, 720.0f * scale); 
      cacheFormatPhoto.scaleMode = HNKScaleModeAspectFit; 
      cacheFormatPhoto.compressionQuality = 0.5f; 
      cacheFormatPhoto.diskCapacity = 50 * 1024 * 1024; // 50MB 
      cacheFormatPhoto.preloadPolicy = HNKPreloadPolicyNone; 
      [[HNKCache sharedCache] registerFormat:cacheFormatPhoto]; 
     } 

``

e qui è l'esempio per la creazione di immagini memorizzate nella cache (TableViewCell contiene CollectionView con le miniature):

``

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    VideoCell *cell = (VideoCell *)[super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    VideoAsset *asset = (VideoAsset *)[self.fetchedResultsController objectAtIndexPath:indexPath]; 
    if ([asset thumbnails] == 0) 
    { 
     MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:[cell thumbnails]]; 
     hud.removeFromSuperViewOnHide = YES; 
     [[cell thumbnails] addSubview:hud]; 
     hud.labelText = NSLocalizedString(@"H11",nil); 
     [hud show:YES]; 
     CGFloat scale = [[UIScreen mainScreen] scale]; 
     CGSize size = CGSizeMake(100.0f * scale, 56.0f *scale); 
     __weak typeof(cell) weakCell = cell; 
     [asset generateThumbnails:self->thumbnailsCount offset:self->thumbnailsOffset size:size completion:^(NSArray *thumbnails) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [hud hide:YES]; 
      }); 
      if ((thumbnails != nil) && ([thumbnails count] > 0)) 
      { 
       HNKCache *cache = [HNKCache sharedCache]; 
       NSUInteger n = 0; 
       NSUInteger keyHash = [[[asset assetURL] absoluteString] hash]; 
       for (UIImage *image in thumbnails) 
       { 
        [cache setImage:image forKey:[NSString stringWithFormat:@"%[email protected]%i",(unsigned long)keyHash,(int)(n++)] formatName:CACHE_FORMAT_THUMBNAIL]; 
        dispatch_async(dispatch_get_main_queue(), ^{ 
         if (weakCell != nil) 
         { 
          __strong typeof(cell) strongCell = weakCell; 
          [[strongCell thumbnails] reloadData]; 
         } 
        }); 
formatName:CACHE_FORMAT_PHOTO]; 
       } 
      } 
     }]; 
    } 
    return (UITableViewCell *)cell; 
} 

``

e l'utilizzo (vista di cella di raccolta della collezione nella cella vista tabella):

``

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    ThumbnailCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; 
    NSString *key = [NSString stringWithFormat:@"%[email protected]%i",(unsigned long)[[[(VideoAsset *)self->_selectedObject assetURL] absoluteString] hash],(int)[indexPath item]]; 
    [cell setKey:key]; 
    [cell setTag:[indexPath item]]; 
    __weak typeof(cell) weakCell = cell; 
    [[HNKCache sharedCache] fetchImageForKey:key formatName:CACHE_FORMAT_THUMBNAIL success:^(UIImage *image) { 
     [[weakCell image] setImage:image]; 
    } failure:^(NSError *error) { 
     if ([[error domain] isEqualToString:HNKErrorDomain] && ([error code] == HNKErrorImageNotFound)) 
     { 
      [[weakCell image] setImage:[UIImage imageNamed:@"movieplaceholder"]]; 
     } 
     else [error reportError]; 
    }]; 
    return cell; 
} 

``

+0

Grazie, lo controllerò! –

+0

SDWebImage utilizza CoreData SQLite DB per la memorizzazione nella cache degli URL. Non ha metodi per immagini "a mano libera" ma è diffuso in tutto il mondo nelle applicazioni ~ REST che scaricano immagini da internet. Lo sto usando appena pubblicato nell'app AppHosters MyHairDressers. –

+0

So che è molto utile per il recupero online, mentre sto usando le immagini create localmente .. E ho bisogno di tenerli un po 'come sulla cache, almeno riempire la cache e solo loro li memorizzano –