NSURLSession 内存泄漏

Nay*_*aik 1 memory-leaks objective-c ios

在 xcode 仪器中,我遇到此方法内存泄漏

- (void)getDataForRequest:(NSURLRequest *)request completionHandler:(downloadCompletionBlock)completionHandler
{
    self.expectedLength = 0;
    self.currentLength = 0;
    self.responseData = Nil;
    
    self.contentLengthBlock = nil;
    self.completionBlock = completionHandler;
    
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
    
    self.postDataTask = [session dataTaskWithRequest:request];
    
    [self.postDataTask resume];
}
Run Code Online (Sandbox Code Playgroud)

Rob*_*Rob 6

此代码片段中的一个问题是,您正在NSURLSession为每个请求创建一个新请求,并且永远不会使会话无效。如果您finishTasksAndInvalidate在发起请求后调用,它将:

\n
    \n
  • NSURLSession当请求完成时回收与相关的内存;通过这样做,它也将
  • \n
  • 释放对该对象的强引用delegate
  • \n
\n

因此:

\n
- (void)getDataForRequest:(NSURLRequest *)request completionHandler:(DownloadCompletionBlock)completionHandler {\n    self.expectedLength = 0;\n    self.currentLength = 0;\n    self.responseData = nil;\n\n    self.contentLengthBlock = nil;\n    self.completionBlock = completionHandler;\n\n    NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];\n    NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];\n\n    self.postDataTask = [session dataTaskWithRequest:request];\n\n    [self.postDataTask resume];\n    [session finishTasksAndInvalidate];\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果你不这样做finishTasksAndInvalidate,你\xe2\x80\x99会看到像这样的泄漏:

\n

在此输入图像描述

\n

打电话finishTasksAndInvalidate就能解决这些问题。

\n
\n

还有另外两种(首选)替代方案:

\n
    \n
  • 如果您仅使用委托来处理响应正文,那么您可以使用完成处理程序块模式来datataskwithurl:completionHandler:代替,那么您可能根本不需要使用委托协议。然后您就可以使用[NSURLSession sharedSession],并且您根本不需要担心会话失效;

    \n
  • \n
  • 如果您确实需要委托(例如,处理身份验证质询请求、检测重定向等),您仍然可以重新考虑是否需要/想要为每个请求创建新会话。\xe2\x80\x99 通常更适合实例化单个NSURLSession,保存对其的引用,并使用该单个NSURLSession(及其关联的委托)来处理多个请求。它更加高效,并且再次使您无需在每次请求后使会话失效。

    \n
  • \n
\n