前回、前々回とNSURLSessionを取り扱ってきた。
[iOS] NSURLSessionを使って通信を行う
[iOS] NSURLSessionでマルチパートデータを送信する
NSURLSessionはとても便利だが、しっかりとセッションの後処理をしないとメモリリークが発生するようだ。
公式ドキュメントにこのように書いてある。
NSURLSession Class Reference
The session object keeps a strong reference to the delegate until your app explicitly invalidates the session. If you do not invalidate the session by calling the
[iOS] NSURLSessionを使って通信を行う
[iOS] NSURLSessionでマルチパートデータを送信する
NSURLSessionはとても便利だが、しっかりとセッションの後処理をしないとメモリリークが発生するようだ。
公式ドキュメントにこのように書いてある。
NSURLSession Class Reference
The session object keeps a strong reference to the delegate until your app explicitly invalidates the session. If you do not invalidate the session by calling the
invalidateAndCancel
orresetWithCompletionHandler:
method, your app leaks memory.要はセッションはデリゲートを強参照するため、手動で終了処理を行わないといけないようだ。
本当にメモリリークするかLeaksで見てみた。
何度か連続してセッションを実行させていると確かにメモリリークが発生している。
そこで、デリゲートメソッドでセッションの後始末をするようにしてみる。
メモリリークは起きなくなった。
これで解決だ。
では、デリゲートを使わない場合はどうだろう。
実行してみると、この場合でもメモリリークが起きた。
なので、この場合でもこのようにしっかりと後始末をした方が良いだろう。
本当にメモリリークするかLeaksで見てみた。
何度か連続してセッションを実行させていると確かにメモリリークが発生している。
そこで、デリゲートメソッドでセッションの後始末をするようにしてみる。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { [session invalidateAndCancel]; }結果はこうだ。
メモリリークは起きなくなった。
これで解決だ。
では、デリゲートを使わない場合はどうだろう。
NSURLSessionDataTask* task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }];このようにcompletionHandlerを指定する場合だ。
実行してみると、この場合でもメモリリークが起きた。
なので、この場合でもこのようにしっかりと後始末をした方が良いだろう。
NSURLSessionDataTask* task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { [session invalidateAndCancel]; }];
コメント