NSURLSessionDataTask memory warning app crash

I'm using NSURLSessionDataTask to download a file of size > 1 GB. But I always get memory warning during downloading and eventually my app crashes. I did look into the Apple documentation of NSURLSessionDataTask and it did say that the Data from dataTaskWithRequest is loaded into the memory.


My question is whether I can set some sort of cachePolicy of NSURLMutuableRequest so that the Data is not loaded into the memory.

Thanks

Replies

My question is whether I can set some sort of cachePolicy of NSURLMutuableRequest so that the Data is not loaded into the memory.

That depends on how you create your data task. If you use the convenience initialisers (for example,

-dataTaskWithRequest:completionHandler:
), the completion handler is called with an NSData object containing the response body, so that obviously has to be all loaded into memory at that point. OTOH, if you use the standard initialiser (for example,
-dataTaskWithRequest:
), data is passed to you via a delegate callback (
-URLSession:dataTask:didReceiveData:
) and thus does not need to be loaded in memory all at once.

The cache policy shouldn’t really matter in this case. The cache will only accept responses up to a certain size, and your responses are definitely too big to be cached.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the quick response.


I forgot to mention, I do use dataTaskWithRequest:completionHandler. But my app always crash before the completionHandler is called. In my opinion, when the delegate, didRecieveData:, is called, the data in this delegate's parameter is loaded into memory.


NOTE: I'm not using downloadTaskWithRequest for downloading because I had some issues regarding resuming the download if the resumeData returned by cancelByProducingResumeData method returned nil. That's why I used range requests along with dataTaskWithRequest:completionHandler to download the file and handle cancel/resume cases.

I do use dataTaskWithRequest:completionHandler. But my app always crash before the completionHandler is called.

Well that’s a clear explanation for the crash you’re seeing. The completion handler block is called with an NSData containing the entire response body. If the response body is huge, the process will be killed while its accumulating that data, and hence it’ll crash before the completion handler is called.

when the delegate, didRecieveData:, is called, the data in this delegate's parameter is loaded into memory.

Right, but this is only one chunk of the data. For a large response body you’ll get multiple

-URLSession:dataTask:didReceiveData:
callback, each with progressive chunks of that response body.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ok great. That pretty much makes sense now. But I still have one issue. You're saying that in the delegate, URLSession:dataTask:didReceiveData:, only one chunk of data will be loaded into memory.


My question now is

Will the chunks pile up in the memory on every received callback? Or will it get removed from the memory after some time?

And I use that chunk of data to write to a file in every callback. In this scenario, I'm not using dataTaskWithRequest:completionHandler.

will the chunks pile up in the memory on every received callback

Not this.

[will] the OS will free up the chunk from the memory after every callback?

But this.

And I use that chunk of data to write to a file in every callback.

That’s a pretty common approach (in fact, it’s more-or-less what NSURLSessionDownloadTask does).

In this scenario, I'm not using dataTaskWithRequest:completionHandler.

Right.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"