在IOS中使用Web服务时会发生NSURLSession内存泄漏 [英] NSURLSession Memory Leaks occur when using web services in IOS
问题描述
我正在构建一个使用Web服务的应用程序,并从我使用的Web服务获取信息 NSURLSession
和 NSURLSessionDataTask
。
I am building an app that uses a web service and to get information from that web service I use NSURLSession
and NSURLSessionDataTask
.
我现在处于内存测试阶段,我发现 NSURLSession
导致内存泄漏。
I am now in the memory testing phase and I have found that NSURLSession
is causing memory leaks.
这不是所有泄漏。这就是我能够适应的情况。
以下是我如何设置 NSURLSession
并从Web服务请求信息。
Below is how I setup the NSURLSession
and request the information from the web service.
#pragma mark - Getter Methods
- (NSURLSessionConfiguration *)sessionConfiguration
{
if (_sessionConfiguration == nil)
{
_sessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
[_sessionConfiguration setHTTPAdditionalHeaders:@{@"Accept": @"application/json"}];
_sessionConfiguration.timeoutIntervalForRequest = 60.0;
_sessionConfiguration.timeoutIntervalForResource = 120.0;
_sessionConfiguration.HTTPMaximumConnectionsPerHost = 1;
}
return _sessionConfiguration;
}
- (NSURLSession *)session
{
if (_session == nil)
{
_session = [NSURLSession
sessionWithConfiguration:self.sessionConfiguration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
#pragma mark -
#pragma mark - Data Task
- (void)photoDataTaskWithRequest:(NSURLRequest *)theRequest
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Photo Request Data Task Set");
#endif
// Remove existing data, if any
if (_photoData)
{
[self setPhotoData:nil];
}
self.photoDataTask = [self.session dataTaskWithRequest:theRequest];
[self.photoDataTask resume];
}
#pragma mark -
#pragma mark - Session
- (void)beginPhotoRequestWithReference:(NSString *)aReference
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Fetching Photo Data...");
#endif
_photoReference = aReference;
NSString * serviceURLString = [[NSString alloc] initWithFormat:@"%@/json?photoreference=%@", PhotoRequestBaseAPIURL, self.photoReference];
NSString * encodedServiceURLString = [serviceURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
serviceURLString = nil;
NSURL * serviceURL = [[NSURL alloc] initWithString:encodedServiceURLString];
encodedServiceURLString = nil;
NSURLRequest * request = [[NSURLRequest alloc] initWithURL:serviceURL];
[self photoDataTaskWithRequest:request];
serviceURL = nil;
request = nil;
}
- (void)cleanupSession
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Session Cleaned Up");
#endif
[self setPhotoData:nil];
[self setPhotoDataTask:nil];
[self setSession:nil];
}
- (void)endSessionAndCancelTasks
{
if (_session)
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Session Ended and Tasks Cancelled");
#endif
[self.session invalidateAndCancel];
[self cleanupSession];
}
}
#pragma mark -
#pragma mark - NSURLSession Delegate Methods
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Session Completed");
#endif
if (error)
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Photo Request Fetch: %@", [error description]);
#endif
[self endSessionAndCancelTasks];
switch (error.code)
{
case NSURLErrorTimedOut:
{
// Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"RequestTimedOut" object:self];
}
break;
case NSURLErrorCancelled:
{
// Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"RequestCancelled" object:self];
}
break;
case NSURLErrorNotConnectedToInternet:
{
// Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotConnectedToInternet" object:self];
}
break;
case NSURLErrorNetworkConnectionLost:
{
// Post notification
[[NSNotificationCenter defaultCenter] postNotificationName:@"NetworkConnectionLost" object:self];
}
break;
default:
{
}
break;
}
}
else {
if ([task isEqual:_photoDataTask])
{
[self parseData:self.photoData fromTask:task];
}
}
}
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
if (error)
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Session Invalidation: %@", [error description]);
#endif
}
if ([session isEqual:_session])
{
[self endSessionAndCancelTasks];
}
}
#pragma mark -
#pragma mark - NSURLSessionDataTask Delegate Methods
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Received Data");
#endif
if ([dataTask isEqual:_photoDataTask])
{
[self.photoData appendData:data];
}
}
#pragma mark -
问题:
为什么 NSURLSession
导致这些内存泄漏?当我完成它时,我使 NSURLSession
无效。我也发布了我不需要的任何属性并将会话设置为nil(参考 - (void)cleanupSession& - (void)endSessionAndCancelTasks)。
Question:
Why is NSURLSession
causing these memory leaks? I am invalidating the NSURLSession
when I am finished with it. I am also releasing any properties that I do not need and setting the session to nil (refer to - (void)cleanupSession & - (void) endSessionAndCancelTasks).
其他信息:
会话完成并清理后发生内存泄漏。有时,它们也会在我弹出 UIViewController
之后出现。但是,我的所有自定义(GPPhotoRequest和GPSearch)对象和UIViewController都被释放了(我已经确定添加了一个NSLog)。
Other Information:
The memory leaks occur after the session has completed and "cleaned up". Sometimes, they also occur after I have popped the UIViewController
. But, all of my custom (GPPhotoRequest and GPSearch) objects and UIViewController are being dealloced (I've made sure by adding an NSLog).
我试图不发布到很多代码,但我觉得大部分都需要被看到。
I tried not to post to much code, but I felt like most of it needed to be seen.
如果您需要更多信息,请告诉我。非常感谢帮助。
Please let me know if you need any more information. Help is greatly appreciated.
推荐答案
重读 URL加载系统编程指南它转变为我是将 NSURLSession
属性设置为nil得太早。
After rereading the URL Loading System Programming Guide it turns that I was setting the NSURLSession
property to nil too early.
相反,我需要设置 NSURLSession
属性为nil我收到委托消息 URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
,这是有意义的。幸运的是,这是一个小错误。
Instead, I need to set the NSURLSession
property to nil AFTER I receive the delegate message URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
, which makes sense. Luckily, it was a minor mistake.
例如
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
if (error)
{
#ifdef DEBUG
NSLog(@"[GPPhotoRequest] Session Invalidation: %@", [error description]);
#endif
}
if ([session isEqual:_session])
{
[self cleanupSession];
}
}
这篇关于在IOS中使用Web服务时会发生NSURLSession内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!