CloudKit対応CoreDataで大きなバイナリデータを保存すると、その保存以降変更を同期できなくなる場合がある
問題
iPhoneとiPad(どちらも実機)のCoreDataの同期で突然、
- iPadでのCoreDataの何らかの処理→ iPhoneに反映される
- iPhoneでのCoreDataの何らかの処理→iPadに反映されない
※設定アプリで一度iCloudの同期を外したり、再起動しても改善されない
が発生しました。
これは恐らくiPhone側の問題だろうと思い、最後にiPadへ反映できた記録以降のCoreDataの記録を確認したところ、カメラで撮影した画像が保存してありました。試しにこの画像を消したところ全ての同期を再開したのでCoreDataのbinary型の属性に何か設定が足りていないのだろうと推察しています。
対応?
参考記事によるとCoreDataにはexternal storageという設定があり、これによって容量の大きい画像などをレコードではなく、ファイルシステム上で管理できるようになるみたいです。
※参考Core Data で大きめの画像を保存する
これを設定していなかったことが原因な気がするので試してみます。
原因
原因がわかりました。
昨日対応案として挙げたexternal storageの設定は無関係で、CloudKitのレコード設定に問題がありました。
.xcdatamodeldファイルにエンティティや属性等を記述して一度ビルドすれば必要なレコードがCloudKitに自動生成されるのでそのまま実環境にデプロイすれば問題ないかと思ったのですが
※デプロイの仕方は割愛(この記事を参照)
バイナリ型の属性のみ、端末へ実際にデータを入れないと生成されないレコードがあるようです。(手動でも設定できるかもしれません)
- .xcdatamodeldファイルにstoredImage属性を記述してビルドした場合
- ビルドしてさらに端末からstoredImage属性にデータを保存した場合
※黄色のハイライトはスクショミスです。特に意味はありません。
実環境で大きいサイズのバイナリデータを扱った時に*_ckAssetレコードがないと同期処理を保留してしまうようです。
なのでこの問題はCloudtKit Consoleの対応で解決できるため、Xcodeで何か変更する必要はありません。
対応
運用環境のCloudKitに*_ckAssetレコードを含めれば同期を再開します。
※1. *_ckAssetレコードは開発環境の端末で該当エンティティにバイナリデータを保存すれば自動で生成されます。
※2. *_ckAssetレコードが生成された状態の開発環境をデプロイすればOKです。