coredata 非同期データ処理
TRANSCRIPT
永島 次朗 / Jiro Nagashima
Twitter@hedjirog
nana music, inc. / iOS Engineerhttp://nana-music.com
Goal
UI操作を妨害することなく高度なデータ処理をしたい
Goal
• CoreDataをマルチスレッドで扱う手法が有効• 複数のContext• parentContext(iOS5 以上)• performBlock: メソッド(iOS5 以上)
UI操作を妨害することなく高度なデータ処理をしたい
解決策
Agenda
• CoreDataフレームワークの概要• CoreDataとマルチスレッド• 単一/複数Contextによる設計• CoreDataの便利機能• parentContext(iOS5 以上)• performBlock: メソッド(iOS5 以上)
CoreDataフレームワークの概要
Demo
ManagedObjectContext
ManagedObject
ManagedObject
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
CoreDataフレームワークの概要
• 4つのクラスとクラス間の関係
CoreDataフレームワークの概要
ManagedObject
• データを表わすオブジェクト
CoreDataフレームワークの概要
ManagedObjectContext
ManagedObject
ManagedObject
ManagedObject
• オブジェクトの集合を管理• オブジェクトの挿入/更新/削除
PersistentStoreCoordinator
CoreDataフレームワークの概要
ManagedObjectContext
ManagedObject
ManagedObject
ManagedObject
• オブジェクトの永続化• 永続ストアへマッピング
PersistentStore
CoreDataフレームワークの概要
ManagedObjectContext
ManagedObject
ManagedObject
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
• オブジェクトの変更を監視• TableViewの表示と整合性を保つ
TableView
CoreDataとマルチスレッド
単一Contextによる設計• 新規オブジェクト追加時
ManagedObjectContext
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
• 過剰な通知• オブジェクトの更新後のみ通知したい
通知のタイミング1. 空のオブジェクト追加時2. オブジェクト更新時
問題点
単一Contextによる設計• オブジェクト永続化時
ManagedObjectContext
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
• 永続化に処理時間を要するとUI操作を妨害
2. 永続化の所要時間が増加
問題点
1. 負荷の高い更新処理
単一Contextによる設計
• 過度な通知が発生する可能性• 永続化時に処理時間を要してUIを妨害する可能性
複数のContextを作成
複数Contextによる設計
ManagedObjectContext
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
• スレッド毎にContextを作成• メインスレッド:監視対象、永続化向け• バックグラウンド:(オブジェクトの)更新向け
ManagedObjectContext
ManagedObject
Main Thread
Background
複数Contextによる設計
ManagedObjectContext
ManagedObject
PersistentStoreCoordinator
FetchedResultsController
• 適切なタイミングで通知が可能• Context(スレッド)毎に役割分担• 処理負荷の分散
ManagedObjectContext
ManagedObject
Main Thread
Background
オブジェクト更新後にマージ
適切なタイミングで通知
CoreDataの便利機能
• parentContext(iOS5 以上)• Context間での更新内容のマージが容易に• performBlock: メソッド(iOS5 以上)• 非同期処理の記述が容易に
parentContext
ManagedObjectContext
PersistentStoreCoordinator
FetchedResultsController
• 複数のContext間で親子関係を定義できる• setParentContext: メソッドで親Contextを指定
ManagedObjectContext
Main Thread
Background
Parent
親Context
子Context
parentContext
ManagedObjectContext
PersistentStoreCoordinator
FetchedResultsController
• Context間での更新内容のマージが容易に• 子Contextのsave: メソッド呼び出しでマージ
ManagedObjectContext
Main Thread
Background
Parent
親Context
子Contextオブジェクト更新後にマージ
parentContext
ManagedObjectContext
NSMangedObjectContext *parentContext;parentContext = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSMainQueueConcurrencyType];
[parentContext setPersistentStoreCoordinator:_persistentStoreCoordinator];
Main Thread
親Context
• 親Contextの作成
Contextの更新処理を行なうスレッドが決定
parentContext
ManagedObjectContext
NSMangedObjectContext *childContext;childContex = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[childContext setParentContext:parentContext];
Main Thread
親ContextManagedObjectContext
Background
子Context
Parent
• 子Contextの作成
Contextの更新処理を行なうスレッドが決定
親Contextの指定
performBlock:
ManagedObjectContext
[childContext performBlock:^{ // push to parent NSError *error; if (![childContext save:&error]) { // handle error } [parentContext performBlock:^{ NSError *error; if (![parentContext save:&error]) { // handle error } }];}];
Main Thread
親ContextManagedObjectContext
Background
子Context
Parent
非同期で処理が実行される
非同期で処理が実行される
• 非同期処理の記述が容易に
performBlock:
ManagedObjectContext
[childContext performBlock:^{ // push to parent NSError *error; if (![childContext save:&error]) { // handle error } [parentContext performBlock:^{ NSError *error; if (![parentContext save:&error]) { // handle error } }];}];
Main Thread
親ContextManagedObjectContext
Background
子Context
Parent
親Contextへ変更内容をマージ
• parentContextとの組み合わせ
performBlock:
ManagedObjectContext
[childContext performBlock:^{ // push to parent NSError *error; if (![childContext save:&error]) { // handle error } [parentContext performBlock:^{ NSError *error; if (![parentContext save:&error]) { // handle error } }];}];
Main Thread
親ContextManagedObjectContext
Background
子Context
Parent
親Contextの永続化
• parentContextとの組み合わせ
まとめ
• UI操作を妨害しない高度なデータ処理• CoreDataをマルチスレッドで利用する• 複数のContextを用意• parentContext で親子関係を定義• performBlock: メソッドで非同期処理
参考資料
• Multi-Context CoreDatahttp://www.cocoanetics.com/2012/07/multi-context-coredata/
より詳しい情報
• WWDC 2011• Session 303 - What's New in Core Data on iOS• Session 315 - What's New in Core Data on Mac OS X• WWDC 2012• Session 214 - Core Data Best Practices