Reputation: 53
In xcode instruments i am getting this method memory leak
- (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];
}
Upvotes: 1
Views: 798
Reputation: 438297
A problem in this code snippet is that you are creating a new NSURLSession
for every request and you never invalidate the sessions. If you call finishTasksAndInvalidate
after the request is initiated, it will:
NSURLSession
when the request finishes; and by doing so, it will alsodelegate
object.Thus:
- (void)getDataForRequest:(NSURLRequest *)request completionHandler:(DownloadCompletionBlock)completionHandler {
self.expectedLength = 0;
self.currentLength = 0;
self.responseData = nil;
self.contentLengthBlock = nil;
self.completionBlock = completionHandler;
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
self.postDataTask = [session dataTaskWithRequest:request];
[self.postDataTask resume];
[session finishTasksAndInvalidate];
}
If you don't finishTasksAndInvalidate
, you’ll see leaks like so:
Calling finishTasksAndInvalidate
will resolve those issues.
There are two other (preferable) alternatives:
If you are using the delegate solely to process the body of the responses, then you might use the completion-handler block pattern of datataskwithurl:completionHandler:
instead, then you might not need to use the delegate protocol at all. You could then use [NSURLSession sharedSession]
and you don’t need to worry about invalidating the session at all;
If you really need the delegate (e.g., handling auth challenge requests, detecting redirects, etc.), you can still reconsider whether you need/want to create new session for each request. It’s generally preferable to instantiate a single NSURLSession
, save a reference to it, and use that single NSURLSession
(and its associated delegate) for multiple requests. It is more efficient and, again, saves you from needing to invalidate the session after every request.
Upvotes: 7
Reputation: 535989
The problem could be the phrase delegate: self
. An NSURLSession retains its delegate. Thus you are telling the session to retain this instance (probably a view controller). The view controller cannot go out of existence until you invalidate the session.
The solution is: manage your session correctly. Keep a reference to the session so that you can invalidate it later. Even better, make the delegate a lightweight object, different from the view controller, whose memory you can manage.
Upvotes: 0