ios - 防止 UIWebView 无限期分配内存(NSURLCache 显然不起作用)

标签 ios memory-management uiwebview instruments nsurlcache

我一直在努力理解 UIWebView 缓存是如何工作的。由于我的目标是能够管理由 UIWebView 分配的内存(至少,尽可能多),以避免无限期地增加内存和应用程序因此而被杀死。

reading 之后other stackoverflow questionssearching the web ,我决定尝试 NSURLCache sharedURLCache,但我不知道它是如何工作的。

我的测试场景是这个:

我已经为 iOS 5 实现了一个测试应用程序,其中我有一个包含 UIWebView 的单一 View 。此 UiWebview 将加载本地 index.html 文件,如下所示:

// 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];

在这个 index.html 文件中,我有一个 JS 脚本,它从 Flickr 下载一个 JSON,其中包含上传到其公共(public)提要的最新图像。每个图像都附加到一个列表中。整个过程每秒重复一次,直到我们从 feed 中下载了 1000 张图像。看代码:

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();
});

最后,在我的 AppDelegate 中,我按照 post 中的说明设置了 sharedURLCache :

// 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];

但是,不管它应该发生什么,当我打开仪器并运行应用程序检查分配时,内存在我们下载图像时不断增长(最多 20MB),而不是像我预期的那样变平大约 4-6MB如果 UIWebView 将使用此 sharedURLCache 来缓存下载的图像。

Instruments evolution after we reach 1000 images

有人知道我做错了什么吗?我误解了什么吗?我加载页面错误吗? UIWebView 是否为在 JS 中加载的图像使用另一个缓存?

请告诉我您的想法。我真的需要了解这个 sharedURLCache 是如何工作的,以及 UIWebView 如何使用它来缓存 URLRequest、图像……以防它被使用。 我不希望有一个应用程序使用可以不受控制地分配内存的 UIWebView。

最佳答案

你最后是怎么处理的? 我注意到您的 *sharedCache initWithMemoryCapacity 有一个 diskPath 参数,它是 nil

来自 apple doco:

In iOS, path is the name of a subdirectory of the application’s default cache directory in which to store the on-disk cache (the subdirectory is created if it does not exist).

查看 Two Bit Labs 提供的有关如何使用缓存的链接: http://twobitlabs.com/2012/01/ios-ipad-iphone-nsurlcache-uiwebview-memory-utilization/

配置共享缓存

首先,让我们在应用程序启动时(在发出任何请求之前)配置缓存,以便我们可以控制它使用的内存量。在你的 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];
...

上面配置了一个 4MB 的内存缓存和一个 32MB 的磁盘缓存。磁盘缓存将驻留在名为“nsurlcache”的子目录中的默认 iOS 缓存目录中。

响应内存警告

我们在使用 Web View 的应用程序中看到的最常见的崩溃原因是当出现内存警告时由于没有释放足够的内存而被弹出。当您的应用程序收到内存警告时,您应该清除共享缓存以释放内存。在您的 UIApplicationDelegate 中执行此操作:

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

现在,当您在分析器中运行您的应用时,您应该会看到内存使用率趋于平稳,如果您在模拟器中触发内存警告,您应该会看到内存使用率下降。

关于ios - 防止 UIWebView 无限期分配内存(NSURLCache 显然不起作用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15275056/

相关文章:

ios - Facebook 横幅广告尺寸

ios - 创建一个圆形颜色选择器

memory-management - Swift程序中有必要使用autoreleasepool吗?

java - JVM 中的内存分配

ios - 在 UIWebView 中限制重定向和抑制广告

ios - 如何在 iOS 7 中使用 iBeacons 获取设备详细信息,如 UUID 或设备名称

ios - 使用 Swift 代码的应用程序在部署后启动时崩溃

c free() 导致崩溃,但数据本身正常工作并且大小正确

ios - 我什么时候可以使用带有通用链接的 SFSafariViewController、WKWebView 或 UIWebView?

ios - 链接 "Watch on youtube"在 iOS UIWebView 中不起作用?