简体   繁体   English

从服务器下载并保存大量图像时,iOS内存问题(ARC)

[英]iOS Memory issue (ARC) when downloading and saving large ammount of images from server

The following code downloads 700+ images from a server with varying sizes, the issue here is that memory (even with ARC) is never released and eventually a memory warning appears followed by the application exiting. 以下代码从大小不同的服务器上下载了700多个映像,这里的问题是,内存(即使使用ARC)也从未释放过,最终出现内存警告,然后退出应用程序。 I've tried @autoreleasepool in this method and that didn't seem to work. 我已经用这种方法尝试过@autoreleasepool,但似乎没有用。 Also I've tried stopping the for loop at different locations to see if memory is released after it finished, but it isn't. 我也尝试过在不同位置停止for循环,以查看完成后是否释放了内存,但事实并非如此。

This method is called inside a for loop and receives the image url and short name. 此方法在for循环内调用,并接收图像url和短名称。 It has been tried in a background thread and main thread with the same results (memory wise). 已经在后台线程和主线程中尝试了相同的结果(从内存角度来看)。

-(void)saveImage:(NSString*)image name:(NSString*)imageName{     
    int k = 0;
    for (int j = 0; j < [imageName length]; j++) {
        if ([imageName characterAtIndex:j] == '/') {
            k = j;
        }
    }if (k != 0) {
        imageName = [imageName substringFromIndex:k+1];
    }    

    NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", imageName]]; 

    if ([fileManager fileExistsAtPath:fullPath]) {
        [fileManager removeItemAtPath:fullPath error:nil];
    }

    NSURL *url = [NSURL URLWithString:image];
    NSData *data = [[NSData alloc]initWithContentsOfURL:url];
    NSLog(@"Saved: %d:%@", [fileManager createFileAtPath:fullPath contents:data attributes:nil], url); 
    data = nil;
}  


- (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"];
[NSURLCache setSharedURLCache:sharedCache];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.window makeKeyAndVisible];
return YES;
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
NSLog(@"mem warning, clearing cache");
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}

分配

Based on your screenshot, I think the issue is with the NSURL caching rather than the actual NSData objects. 根据您的屏幕截图,我认为问题出在NSURL缓存而不是实际的NSData对象。 Can you try the following: 您可以尝试以下方法:

In your Application Delegate, setup an initial URL cache: 在您的应用程序委托中,设置初始URL缓存:

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

    // Finish the rest of your didFinishLaunchingWithOptions and head into the app proper
}

Add the following to your Application Delegate: 将以下内容添加到您的应用程序委托中:

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

A cache file will be created: "Library/Caches/your_app_id/nsurlcache" 将创建一个缓存文件: "Library/Caches/your_app_id/nsurlcache"

The link to the Apple example is here: URL Cache Apple示例的链接在这里: URL缓存

Code not tested but this (or something similar) should sort your problem + plus you can experiment with the cache sizes. 代码未经测试,但这(或类似的东西)应该可以解决您的问题+您还可以尝试使用缓存大小。

Can you post another screenshot of Allocations in action with this code? 您可以使用此代码发布另一个实际分配屏幕截图吗? I would expect to see memory use stop growing and flatten out. 我希望看到内存使用停止增长并趋于平稳。

" dataWithContentsOfURL " returns an autoreleased NSData object and that doesn't normally get released until the end of the run loop or the end of the method , so it's no wonder you're filling up memory pretty quickly. dataWithContentsOfURL ”返回一个自动释放的NSData对象, 通常直到运行循环结束或该方法结束时才释放该对象,因此也就不足为奇了。

Change it to an explicit " initWithContentsOfURL " method and then force a release by doing " data = nil; " when you are absolutely done with the image data. 将其更改为显式的“ initWithContentsOfURL ”方法,然后在绝对使用完图像数据通过执行“ data = nil; ”来强制释放

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM