NSURLSession内存泄漏
即使使NSURLSession失效,使用Instruments运行configuration文件,一些名为TubeManager的类(可能是私有的),HTTPConnectionCache和HTTPConnectionCacheDictionary在内存中仍然存在。
代码片段重现:
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession* session = [NSURLSession sessionWithConfiguration:config]; NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]]; NSURLSessionDataTask* sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { [session finishTasksAndInvalidate]; }]; [sessionDataTask resume];
那么,问题是什么? 你想closurescaching吗? networking响应通常caching在NSURLCache
内存和永久存储中。
如果此caching使用情况有问题,请相应地更改会话configuration的requestCachePolicy
。 或者更改NSMutableURLRequest
本身的cachePolicy
。 您还可以configuration会话configuration使用的URLCache
的最大大小,以限制RAM使用量以及持久性内存使用量。
即使你closurescaching,一般来说,API调用不会让你感到惊讶,因为API调用会增加内存消耗。 第一次执行某项任务时,应用程序体验到一些适度的内存消耗并不罕见。 但是在应用程序运行时,在后续迭代中不应该看到相同的增长。 在跟踪内存使用情况时,通常build议多次重复任务,看看应用程序是否返回到稳定状态(这是可取的),还是继续增长(这需要进一步调查以确保代码不是问题的来源)。 但是我们很less担心最初的内存消耗,除非它是显着的。
看看你的代码片段,没有什么明显的错误。 我倾向于怀疑iOS的例行内存消耗。 假设问题比一般caching行为更广泛,如果每次应用程序执行此代码时内存消耗剧烈和/或持续增长,则提供更多详细信息,我们可以帮助您进一步诊断。
这是我的内存configuration文件看起来像四批100个请求之后, 加上一个最后的标志后,我发出了记忆警告:
(注意,这是一个合成图像,所以我可以在第一批之前,第三批之前,最后一批之后以及手动发布内存警告之前向您显示内存。我将它们组合在一起,以便更容易地看到总分配在那四个时间点。)
请注意,在iOS 9上,安全框架分配appx。 4k的SSLcaching数据,并在首次为新的NSURLSession对象恢复任务时向您的应用程序收费。 苹果技术问答QA1727告诉我们这个SSLcaching持续10分钟,不pipe是什么,因为它是私人的,完全由系统pipe理(因为安全!)。
在您的代码示例中,每次发出请求时都会创build一个新的NSURLSession对象。 但是你只是使用defaultSessionConfiguration而不是指定一个可能存在强引用的委托,那么你应该做的只是使用单例[NSURLSession sharedSession]
并使用resetWithCompletionHandler
来清除非安全分配。 或者如果你想自定义configuration,则创build一个自定义单例。
- (NSURLSession *)sharedSession讨论
对于基本请求,URL会话类提供了一个共享的单例会话对象,为您提供合理的默认行为。 通过使用共享会话,只需几行代码就可以将URL的内容提取到内存中。
与其他会话types不同,您不会创build共享会话; 你只需要调用[NSURLSession sharedSession]来请求它。 因此,您不提供委托或configuration对象。 因此,与共享会话:
- You cannot obtain data incrementally as it arrives from the server. - You cannot significantly customize the default connection behavior. - Your ability to perform authentication is limited. - You cannot perform background downloads or uploads while your app is not running.
共享会话使用共享的NSURLCache,NSHTTPCookieStorage和NSURLCredentialStorage对象,使用共享的自定义networking协议列表(使用registerClass:和unregisterClass :)configuration,并且基于默认configuration。
在使用共享会话时,通常应避免自定义caching,cookie存储或凭证存储(除非您已经使用NSURLConnection),因为您很可能会超出默认会话的function在这一点上,您将不得不以适合您的自定义URL会话的方式重写所有这些自定义设置。
换句话说,如果您对caching,Cookie,身份validation或自定义networking协议做任何事情,则应该使用默认会话而不是默认会话。
(来自NSURLSession类参考…斜体我的; P)
如果你没有使用sharedSession
苹果提供的单身人士,那么你至less应该从苹果公司获得一个提示,并用会话属性来sharedSession
自己的单身人士。 会议的要点是,它的目的是活得比一个请求更长。 尽pipe他们的文档不清楚,但苹果提供了一个单例,并将其称为“会话”的事实表明,会话对象的寿命要长于单个请求。
是的,你应该在某个时候invalidateAndCancel
,而不是在每一个请求之后,即使每个请求都完全去了一个不同的服务器(这几乎从来就不是这样)。 如果您打算引用特定会话,则只需要使其无效并取消; 否则,可以在会话上调用flushWithCompletionHandler
或resetWithCompletionHandler
来刷新会话的堆分配给VM,或重置以清除堆和VM存储。 (另请参阅我的答案)
finishTasksAndInvalidate在错误的地方调用… completionHandler用于处理响应它与session没有任何关系
这是正确的代码:
NSURLSessionConfiguration* config = [NSURLSessionConfigurationdefaultSessionConfiguration]; NSURLSession* session = [NSURLSession sessionWithConfiguration:config]; NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]]; NSURLSessionDataTask* sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // handle response... }]; [sessionDataTask resume]; [session finishTasksAndInvalidate];
- 非指针types的C ++向量是否会在iOS中导致内存泄漏?
- UIGraphicsGetImageFromCurrentImageContext() – 内存泄漏
- 在启用ARC的C代码中执行Objective-C代码时,运行时内存泄漏警告
- iOS的libsystem_c.dylib strdup内存泄漏NSZombie无法正常工作
- 在使用UIImagePickerControllerOriginalImage从UIImagePickerController获取图像时获取内存警告
- iAd UIImageView内存泄漏
- 如何解决在mapKit Ios中使用的多余内存?
- 内存泄漏与iPad中的大量图像
- 为什么静态NSString泄漏?