web-dev-qa-db-ja.com

コアデータ(iPhone)の「自動軽量移行」の実装

コアデータモデルに新しい属性を追加するときに、アプリで自動軽量移行を実行できるようにしたいと考えています。

Appleからのガイドでこれは私が見つけることができた主題に関する唯一の情報です:

自動軽量移行

自動軽量移行を要求するには、addPersistentStoreWithType:configuration:URL:options:error:で渡すオプションディクショナリに適切なフラグを設定します。 NSMigratePersistentStoresAutomaticallyOptionキーとNSInferMappingModelAutomaticallyOptionキーの両方に対応する値をYESに設定する必要があります。

NSError *error;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

if (![psc addPersistentStoreWithType:<#Store type#>
    configuration:<#Configuration or nil#> URL:storeURL
    options:options error:&error]) {
    // Handle the error.
}

私のNSPersistentStoreCoordinatorは次のように初期化されます:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"FC.sqlite"]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

Appleコードを追加して自動軽量移行を機能させるには?をどこにどのように追加すればよいかわからない

50
RickiG

これは私が自動軽量移行を行うために行ったことです(ソース: http://brainwashinc.wordpress.com/2010/01/18/iphone-coredata-automatic-light-migration/

1.アプリデリゲートで自動移行の永続ストアオプションを設定します。

PersistentStoreCoordinatorの作成を次のように変更します(YOURDBを置き換えます)。

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

  if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
  }

  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"YOURDB.sqlite"]];

  // handle db upgrade
  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
  }

  return persistentStoreCoordinator;
}

2.データモデルにバージョンを付け、新しいファイルを編集します。

Xcdatamodelファイルを選択デザイン->データモデル->モデルバージョンの追加(xcdatamodeldアイテムを展開)「2」(またはそれ以降)ファイルを選択し、デザイン->データモデル->現在のバージョンを設定(このバージョンを編集)

3.アプリデリゲートでmomdリソースを指定します。

ManagedObjectModel実装をこれに変更します(YOURDBを置き換えます)

- (NSManagedObjectModel *)managedObjectModel {

  if (managedObjectModel != nil) {
    return managedObjectModel;
  }

  NSString *path = [[NSBundle mainBundle] pathForResource:@"YOURDB" ofType:@"momd"];
  NSURL *momURL = [NSURL fileURLWithPath:path];
  managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

  return managedObjectModel;
}
93
willi

最初は、上記の解決策ではうまくいきませんでした。返されたmanagedObjectModelは0x0でした。これは、別のモデルファイルのファイル名を変更したためだと思います。上記の指示に従って手紙を書けば、すべてうまくいきます。

ただし、モデルファイル名を変更する場合は、「現在の」モデルファイルを手動で選択できます。上記のモデルの追加手順を実行した後、元のモデルファイルがMYMODEL.xcdatamodelだったとします。これにより、MY.xcdatamodeldディレクトリになり、その下にMYMODEL.xcdatamodelおよびMYMODEL 2.xcdatamodelは、新しいモデルファイルの名前を任意に変更します。たとえば、MYMODEL2.xcdatamodelのスペースを削除して、その内容を編集するとします。今上のコードで

NSString *path = [mainBundle pathForResource:@"MYMODEL2" ofType:@"mom" inDirectory:@"MYMODEL.momd"];
7
udibr

これは最後の答えに追加すると思います。

最初は、バンドルリソースと.sqlite名の使い方が本当にわかりにくいことに気付きました。バンドルリソース名はバージョンの変更に伴って変わりますか? .sqlite名は変更されますか?これで移行が機能し、バンドルモデル名が、そのディレクトリ内のモデルバージョンの名前ではなく、すべてのモデルを含むXCode内のディレクトリ/フォルダーの名前を指すことがわかりました。

ModelResource名を次のように指定すると、

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelResource withExtension:@"momd"];
NSManagedObjectModel *theManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

そのmodelResource名は、Xcodeのモデルのディレクトリ/フォルダーです。

あなたがするとき:

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:storeFileName];
    NSError *error = nil;

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        // handle error
    }

StoreFileNameは、Documentsフォルダー/ディレクトリにある.sqliteファイルの名前です(これはバンドルではnotです)。

また、あるモデルバージョンから別のモデルバージョンに移行する場合、デフォルトでは、.sqliteファイル名は同じままです。

1
Chris Prince

Swift 3ソリューション

1。アプリの委任で自動移行の永続ストアオプションを設定します。

PersistentStoreCoordinatorの作成を次のように変更します(SingleViewCoreData.sqliteを置き換えます)。

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {


let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")

let options = [
  NSMigratePersistentStoresAutomaticallyOption : Int(true),
  NSInferMappingModelAutomaticallyOption : Int(true)
]

do {

  try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)

} catch {

  print(error)
}

return coordinator

}()

2。データモデルにバージョンを付け、新しいファイルを編集します。

Xcdatamodelファイルエディターを選択>モデルバージョンの追加-新しいモデルの名前を追加

0
Ben Sullivan

オスカー、あなたの問題に応えて、最初は同じものを見つけました。新しい.xcdatamodeldファイルを削除してプロジェクトに再度追加してから、再ビルドすることをお勧めします。お役に立てば幸いです。

0
gemmakbarlow