iOS摘

摘要


关于iOS的UIWebView内存泄露的问题,已经存在了很长时间。一直也没有什么好的解决方法。最近因公司的一个项目,因为内存问题一直闪退。为了解决这个问题,在网上找了很多方法,但是基本上都不怎么好用问题依旧。以前也碰到过这个问题,当时的解决方法就是设置NSURLCache大小。因为iOS当中的网络通讯默认都是通过NSURLConnection来实现的。所以UIWebView内部通讯也是通过NSURLConnection来下载网页资源的。


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


并且在收到内存警告的时候,清除缓存内容。

- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application

{

    [[NSURLCache sharedURLCache] removeAllCachedResponses];

}

以及在释放UIWebView的时候
_webView.delegate = nil;

[_webView loadHTMLString:@"" baseURL:nil];

[_webView stopLoading];

[_webView removeFromSuperview];

[[NSURLCache sharedURLCache] removeAllCachedResponses];

[_webView release];

解决这个问题的方法是在webViewDidFinishLoad方法中设置如下:

   [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];//自己添加的,原文没有提到。
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];//自己添加的,原文没有提到。
    [[NSUserDefaults standardUserDefaults] synchronize];



可以编写一个子类,继承于NSURLCache,重载方法cachedResponseForRequest:方法,在此方法里新开辟一个子线程,把网页的数据全部下载下来(主要是html页面、css、js文件以及图片资源)。下次再访问同一个url时,就从本地文件读取html页面,而不是再次向网络请求。 


不加载完整的图片到内存的情况下获取图片属性


    //Some path
    NSString*path=[[[NSBundlemainBundle] resourcePath] stringByAppendingPathComponent:@"back-btn.png"];
    NSURL*imageFileURL=[NSURL fileURLWithPath:path];
    CGImageSourceRefimageSource=CGImageSourceCreateWithURL((__bridgeCFURLRef)imageFileURL,NULL);
    if(imageSource){
        NSDictionary*options=@{(NSString*)kCGImageSourceShouldCache:@NO};
        CFDictionaryRefimageProperties=CGImageSourceCopyPropertiesAtIndex(imageSource,0,(__bridgeCFDictionaryRef)options);
        if(imageProperties){
            NSLog(@"properties: %@",imageProperties);
            CFRelease(imageProperties);
        }
    }else{
        NSLog(@" Error loading image");
    }


具体的方式如下:

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

同时追加内存警告时的处理:

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

经实机测试,的确会降低系统内存的用量,但应用本身的内存占用量没有大的变化。

以上调查结果,仅供参考。


- (void)webViewDidFinishLoad:(UIWebView *)webView{
    [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];//自己添加的,原文没有提到。
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];//自己添加的,原文没有提到。
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    if (IS_PHONE) {
        self.imageURLArray=[[[NSMutableArray alloc]initWithArray:[self getWebViewPictureUrlString]]autorelease];
        dispatch_queue_t queue=dispatch_queue_create("imagedownload", NULL);
        dispatch_async(queue, ^{
            [self asynRequestForImageArr:self.imageURLArray fromIndex:0];
        });
        dispatch_release(queue);
    }
    
}


xxxxxxxxxxxxxxx


你可能感兴趣的:(iOS摘)