即使在使NSURLSession无效后,使用工具运行配置文件,一些名为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];

发布于 2015-05-08 01:58:04
那么,问题是什么呢?是否要关闭缓存?网络响应通常缓存在内存和持久存储中的NSURLCache中。
如果此缓存使用有问题,请相应地更改会话配置的requestCachePolicy。或者更改NSMutableURLRequest本身的cachePolicy。您还可以配置会话配置使用的URLCache的最大大小,以限制内存使用量和持久内存使用量。
即使您关闭了缓存,作为一般规则,人们也不应对API调用增加内存消耗感到惊讶,这并非您自己的错误。对于一个应用程序来说,在第一次执行某些任务时遇到一些适度的内存消耗并不少见。但在应用程序运行时,在后续迭代中不应看到相同的增长。在跟踪内存使用情况时,通常建议多次重复该任务,并查看应用程序是否返回到某种稳定状态(这是可取的),或者它是否继续增长(这需要进一步调查以确保您的代码不是问题的根源)。但我们很少担心初始内存消耗,除非它是戏剧性的。
查看您的代码片段,没有明显的错误。我倾向于怀疑iOS的例程内存消耗。假设问题比一般的缓存行为更广泛,如果每次应用程序执行此代码时内存消耗很大和/或继续增长,那么请提供更多详细信息,我们可以帮助您进一步诊断此问题。
这是我的内存配置文件在四批100个请求之后的样子;加上我发出内存警告后的最后一个标志:

(注意,这是一个合成图像,所以我可以在第一批之前、第三批之前、最后一批之后以及在我手动发布内存警告之后显示内存。我将它们组合在一起,以便更容易地查看这四个时间点的总分配情况。)
发布于 2016-03-06 04:05:54
请注意,在iOS 9上,安全框架分配appx。4k的SSL缓存数据,并在您第一次为新的NSURLSession对象恢复任务时将其计入您的应用程序。Apple Technical Q&A QA1727告诉我们,这个SSL缓存会持续10分钟,因为它是私有的,完全由系统管理(因为安全性!)。
在您的代码示例中,每次发出请求时都会创建一个新的NSURLSession对象。但是您只是使用defaultSessionConfiguration,而没有指定一个可能存在强引用的委托,那么您应该做的是使用单例[NSURLSession sharedSession]并使用resetWithCompletionHandler来清除非安全分配。或者,如果您想要自定义配置,也可以创建一个自定义单例。
对于基本请求,URL会话类提供了一个共享的单例会话对象,该对象为您提供了合理的默认行为。通过使用共享会话,只需几行代码就可以将URL的内容提取到内存中。
与其他会话类型不同,您不需要创建共享会话;您只需通过调用NSURLSession sharedSession来请求它。因此,您不需要提供委托或配置对象。因此,使用共享会话:
- 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对象,使用共享的自定义网络协议列表(使用registerClass:和unregisterClass:配置),并且基于默认配置。
在使用共享会话时,通常应避免自定义缓存、cookie存储或凭据存储(除非您已经在使用NSURLConnection执行此操作),因为很有可能最终会超出默认会话的能力,此时您必须以一种与自定义URL会话一起工作的方式重写所有这些自定义。
换句话说,如果您正在使用缓存、cookie、身份验证或自定义网络协议执行任何操作,那么您可能应该使用默认会话,而不是默认会话。
(来自NSURLSession类参考...斜体矿山;P)
如果你没有使用苹果提供的sharedSession单例,那么你至少应该从苹果那里得到一个提示,并使用会话属性来滚动你自己的单例。会话的意义在于,它的生存时间不只是一个请求。尽管他们的文档不清楚,但事实上苹果提供了一个单例,并将其称为“会话”,这表明会话对象的生存时间应该比单个请求更长。
是的,你应该在某个时刻invalidateAndCancel,但不是在每个请求之后,甚至不是每个请求都去往完全不同的服务器(这几乎从来不是这种情况)。如果要中断对特定会话的引用,则只需使其无效并取消;否则,只需在该会话上调用flushWithCompletionHandler或resetWithCompletionHandler将会话的堆分配刷新到VM,或者重置以清除堆和VM存储。(另请参阅我的答案here。)
发布于 2017-10-08 13:51:08
finishTasksAndInvalidate在错误的位置调用...completionHandler是用于处理响应的,它与会话无关
下面是正确的代码:
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];https://stackoverflow.com/questions/30106960
复制相似问题