2013-03-07 1 views
6

J'ai essayé de comprendre le fonctionnement du cache UIWebView. Depuis mon objectif est pour pouvoir gérer la mémoire allouée par le UIWebView (au moins, autant que possible), pour éviter la hausse de la mémoire indéfiniment et l'application se faire tuer à cause de cela.Empêcher UIWebView d'allouer de la mémoire indéfiniment (NSURLCache apparemment ne fonctionne pas)

Après readingotherstackoverflowquestions et searchingtheweb, j'ai décidé d'essayer le NSURLCache sharedURLCache, mais je ne peux pas comprendre comment cela fonctionne vraiment.

Mon scénario de test est celui-ci:

J'ai mis en place une application de test pour iOS 5 où j'ai une seule vue avec un UIWebView intérieur. Ce UIWebView va charger un fichier index.html locale comme ceci:

// Create an NSString from the local HTML file 
NSString *fullURL = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"]; 
NSURL *url = [NSURL fileURLWithPath:fullURL]; 
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; 
// Load local HTML file 
[self.webView loadRequest:requestObj]; 

Dans ce fichier index.html, j'ai un script JS qui télécharge un JSON de Flickr avec les dernières images téléchargées sur leur alimentation publique. Chaque image est ajoutée à une liste. Tout ce processus est répété chaque seconde, jusqu'à ce que nous atteignions 1000 images téléchargées à partir du flux. Voir le code:

var nImg = 0; 

function getData() 
{ 
    $.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?format=json&jsoncallback=?', function(data) 
    { 
     var items = []; 
     $.each(data.items, function(i, image) { 
      items.push('<li id="' + image.title + '"><img src="' + image.media.m + '"/></li>'); 
     }); 
     $('#page > #imagesList').append(items.join'')); 
     nImg += items.length; 
    }); 
    $('#page > #numImages').html(nImg); 

    if(nImg < 1000) 
     setTimeout("getData();", 1000); // Get more data in 1s 
} 

$(document).ready(function() 
{ 
    getData(); 
}); 

Enfin, dans mon AppDelegate, je mis le sharedURLCache comme il est écrit dans ce post:

// Initialize the Cache, so we can control the amount of memory it utilizes 
int cacheSizeMemory = 4*1024*1024; // 4MB 
int cacheSizeDisk = 32*1024*1024; // 32MB 
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:nil]; 

[NSURLCache setSharedURLCache:sharedCache]; 

Mais, en dépit de ce qu'il est censé se produire, quand j'ouvre des instruments et Exécutez l'application en vérifiant les allocations, la mémoire ne cesse de croître pendant que nous téléchargeons des images (jusqu'à 20 Mo), au lieu d'aplatir autour de 4-6 Mo comme je m'attendais si UIWebView utiliserait ce sharedURLCache partagé pour mettre en cache les images téléchargées.

Instruments evolution after we reach 1000 images

Quelqu'un sait-il ce que je fais mal? Ai-je mal compris quelque chose? Est-ce que je charge la page mal? Est-ce que UIWebView utilise un autre cache pour les images chargées dans le JS?

S'il vous plaît, laissez-moi savoir vos pensées. J'ai vraiment besoin de comprendre comment ce sharedURLCache fonctionne, et comment UIWebView l'utilise pour mettre en cache URLRequest, images, ... au cas où il serait utilisé. Je ne veux pas avoir une application qui utilise un UIWebView qui peut allouer de la mémoire sans contrôle.

Répondre

1

Comment cela s'est-il passé? Je remarque que votre *sharedCache initWithMemoryCapacity a un argument diskPath qui est nil.

De la doco pomme:

Dans iOS, le chemin est le nom d'un sous-répertoire du répertoire de cache par défaut de l'application dans lequel stocker le cache sur disque (le sous-répertoire est créé si n'existe pas).

Commander ce lien par deux bits Labs sur la façon d'utiliser le cache: http://twobitlabs.com/2012/01/ios-ipad-iphone-nsurlcache-uiwebview-memory-utilization/

Configuration du cache partagé

Tout d'abord, nous allons configurer le cache au démarrage de l'application (avant toute demande sont fait) afin que nous puissions contrôler la quantité de mémoire qu'il utilise. Dans votre UIApplicationDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    int cacheSizeMemory = 4*1024*1024; // 4MB 
    int cacheSizeDisk = 32*1024*1024; // 32MB 
    NSURLCache *sharedCache = [[[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"] autorelease]; 
    [NSURLCache setSharedURLCache:sharedCache]; 
... 

Le configure au dessus d'un cache de 4 Mo en mémoire avec un cache de disque de 32 Mo. Le cache disque se trouve dans le répertoire de cache iOS par défaut dans un sous-répertoire appelé "nsurlcache".

En réponse aux avertissements de mémoire

La cause la plus fréquente d'accidents que nous avons vu dans les applications qui utilisent des vues Web est éjecté pour ne pas libérer suffisamment de mémoire quand un avertissement de mémoire entre en jeu. Lorsque votre application reçoit une mémoire avertissement, vous devez purger le cache partagé pour libérer de la mémoire. Faites ceci dans votre UIApplicationDelegate:

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 
    [[NSURLCache sharedURLCache] removeAllCachedResponses]; 
} 

Maintenant lorsque vous exécutez votre application dans le profileur, vous devriez voir l'utilisation de la mémoire aplatissent, et si vous déclenchez un avertissement de mémoire dans le simulateur, vous devriez voir la chute de l'utilisation de la mémoire.

+0

Merci pour la réponse! Je n'ai pas compris quel était le problème et le lien que vous citez est le même que celui que je suivais pour faire ce test (vous pouvez voir que je l'ai lié dans ma question): $ – veducm

Questions connexes