iOS 14で再確認すると修正済み
この記事の初版を投稿した頃の最新OSはiOS 8.1でした。当時は、この記事の後半に残してあるような問題がありました。しかし、iOS 14で再確認してみると問題は修正されていました。
テストアプリを作成し、約12GBのファイルをHTTPでダウンロードさせてみました。iOS 8.1の頃のような問題は再現せず、メモリの上昇も見られませんでした。iPhone Xsで試してみると、41MB付近で微増という感じでした。
NSURLConnectionやCFNetworkを使ったダウンロード処理に使用するAPIは既に非推奨APIになっています。そのため、NSURLSession (SwiftではURLSession) に移行する必要があります。
確認に使用したテストコードはGitHubの以下のリポジトリに置いておきます。
iOS 8.1の頃の話
NSURLSessionですが、ダウンロードしたデータをオンメモリ(NSData)で渡してくれるメソッドとテンポラリファイルに書き込んで渡してくれるメソッドの両方がいます。普通に考えれば、テンポラリファイルの方は、ファイルに書きながらなので、巨大なファイルも扱えると思うのですが、iOS 8.1で見ていると、どうも中間のデータをオンメモリで持っていて、最後に書いている様子。そのため、途中でメモリ不足になって落ちてしまいます。
通信の後に、invalidateAndCancelで解放してあげないと、リークになることは明記されていますが、途中のデータの扱いがオンメモリで持っているかについては書かれていません。しかし、Instrumentsで見てみると、CFNetworkを内部で使っていて、データ受信用のコールバック関数の中で確保しているデータがダウンロード中は解放されていないことが確認できます。
これでは、巨大なファイルを落とす可能性があるアプリでは使えないですね。。。
巨大なファイルを落とす可能性があるアプリではNSURLConnectionやCFNetworkのAPIを使ってダウンロード処理を書いた方が良いようです。
投稿者プロフィール

- macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者
- アールケー開発代表。macOS/iOSアプリ/SDK/ミドルウェア開発が専門の開発者。ObjC/Swift/C++使い。豊富な開発実務経験を基に、教育コンテンツ開発、技術書執筆、技術指導、技術セミナー講師、企業内研修講師、行政・自治体職員研修講師も行います。
最新の投稿
アプリ開発2021.04.19Xcodeでフレームワークや共有ライブラリの出力シンボルを制御する
アプリ開発2021.04.11SwiftのUnsafeMutableBufferは[]演算子よりも速い
アプリ開発2021.04.10SwiftでCのポインタのインクリメント・デクリメントのコードを書き換える
アプリ開発2021.04.07M1 MacへのAndroid Studioのセットアップ