2018年10月19日金曜日

CoreDataでExternal Storage使ってたら死んだ話

久しぶりの投稿です。

問題発生

仕事でiOSアプリの受託開発をしているのですが、顧客から「iOS 12にアップデートしたらアプリが動かなくなった」と指摘がありました。
クラッシュダンプを見ていると、CoreDataにExternal Storageとして保存していたNSData?をForce Unwrapしたところ、nilになっているためFatal Errorという状態でした。

詳しい内容は以下の記事で検証されているので省きます。
ios12でCoreDataのExternal Storageを利用しているデータが破損してしまう問題が発生した件


さすがにデータが入っていることを確認した上で保存してるし、いままで正常に動いていたのにiOS 12にした途端100%落ちるし、これはおかしいと思い「iOS 12 CoreData Bug」で検索していたところ以下を発見。

iOS 12 specific problem: Core Data External Storage Binary Data corruption

正直、どうしようもない。

対処

一応iOS 12.1のベータではこのバグは修正されているらしいですが、ユーザがアップデートしてくれないとどうしようもないので、External Storageで保存していたファイルをすべて手動でファイルシステムに保存するように書き換えました。
NSManagedObjectのExtensionとかで保存の処理を書いて置くとちょっとはマシかも知れない。CoreDataのレコードとファイルの有無をちゃんと整合性取るようにしないといけないので面倒ではあるけど。

ちなみにこの修正をしているときにクソどうでもいいところでハマったので共有します。


一部のファイルはアクセス不能になっていたものの、ちゃんとアクセスできるファイルも残っている状態だったので、アプリの起動時にファイルを移動して、壊れているレコードは削除する処理を書こうと思ったのですが、



↑このように書いても、DB上ではExternal Storageのファイル保存先のパスが入っているため、当然引っかかりません。
各レコードに対して、保存したファイルがちゃんとアクセスできる状態にあるかを確認する必要があります。(ManagedObjectにしてしまえばnilが入るので判別できる)


体調が悪い中、このパッチを書くために時間外労働をするはめになってしまった。
iOS本体のバグは本当にやめてほしい。

External Storage(というかCoreData)はおすすめしませんという話でした。

0 件のコメント:

コメントを投稿