[Leopard] Core Data model versioning vs. NSPersistentDocument

  • Hi!

    Does NSPersistentDocument handle versioning issues or do I need to
    hook into document loading to call the migration manager myself?

    What is the recommended approach for using the migration manager
    within the NSDocument architecture?

    Thanks in advance,
    Pierre

    ---
    Pierre Bernard
    http://www.bernard-web.com/pierre
    http://www.houdah.com
  • On Oct 31, 2007, at 4:00 PM, Pierre Bernard wrote:

    > Does NSPersistentDocument handle versioning issues or do I need to
    > hook into document loading to call the migration manager myself?
    > What is the recommended approach for using the migration manager
    > within the NSDocument architecture?
    >
    It's just as described here <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataVersionin
    g/Articles/vmInitiating.html
    >.

    mmalc
  • Hi!

    Thanks Malcolm.

    I got at least one step closer to the solution, still it does not work
    yet.

    Here is where I pass the appropriate option to the store coordinator:

    - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url
                                             ofType:(NSString *)fileType
                                 modelConfiguration:(NSString *)configuration
                                        storeOptions:(NSDictionary *)storeOptions
              error:(NSError **)error
    {
    NSMutableDictionary *options = [NSMutableDictionary
    dictionaryWithDictionary:storeOptions];

    [options setObject:[NSNumber numberWithBool:YES]
    forKey:NSMigratePersistentStoresAutomaticallyOption];

        BOOL ok = [super configurePersistentStoreCoordinatorForURL:url
                                                            ofType:fileType
              modelConfiguration:configuration
                                                     storeOptions:options
                                                              error:error];

    if (*error != nil) {
      NSLog(@"sourceModel: %@", [[*error userInfo]
    valueForKeyPath:@"sourceModel.versionIdentifiers"]);
      NSLog(@"destinationModel: %@", [[*error userInfo]
    valueForKeyPath:@"destinationModel.versionIdentifiers"]);
      NSLog(@"same model: %@", ([[*error userInfo]
    valueForKeyPath:@"sourceModel"] == [[*error userInfo]
    valueForKeyPath:@"destinationModel"]) ? @"YES" : @"NO");
      NSLog(@"equivalent model: %@", ([[[*error userInfo]
    valueForKeyPath:@"sourceModel"] isEqual:[[*error userInfo]
    valueForKeyPath:@"destinationModel"]]) ? @"YES" : @"NO");
      NSLog(@"reason: %@", [[*error userInfo] valueForKeyPath:@"reason"]);

    }

        return ok;
    }

    The problem is that ok == NO. I.e. migration fails and I have no idea
    where to look for hints or explanations. The error is pretty
    meaningless except for its userInfo dictionary. Moreover the error is
    swallowed on the way up to the user where it appears as a generic
    "cannot open" message.

    Now what I can't understand is why both source and destination models
    have the same versionIdentifiers. I guess this would also explain why
    the mapping model is not found.

    Best,
    Pierre

    On Nov 1, 2007, at 3:23 AM, mmalc crawford wrote:

    >
    > On Oct 31, 2007, at 4:00 PM, Pierre Bernard wrote:
    >
    >> Does NSPersistentDocument handle versioning issues or do I need to
    >> hook into document loading to call the migration manager myself?
    >> What is the recommended approach for using the migration manager
    >> within the NSDocument architecture?
    >>
    > It's just as described here <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataVersionin
    g/Articles/vmInitiating.html
    > >.
    >
    > mmalc
    >

    ---
    Pierre Bernard
    http://www.bernard-web.com/pierre
    http://www.houdah.com
  • Now this is odd:

    I have added some more debugging output.

      MLogString(@"sourceModel: %@", [[*error userInfo]
    valueForKeyPath:@"sourceModel.versionIdentifiers"]);
      MLogString(@"destinationModel: %@", [[*error userInfo]
    valueForKeyPath:@"destinationModel.versionIdentifiers"]);
      MLogString(@"same model: %@", ([[*error userInfo]
    valueForKeyPath:@"sourceModel"] == [[*error userInfo]
    valueForKeyPath:@"destinationModel"]) ? @"YES" : @"NO");
      MLogString(@"equivalent model: %@", ([[[*error userInfo]
    valueForKeyPath:@"sourceModel"] isEqual:[[*error userInfo]
    valueForKeyPath:@"destinationModel"]]) ? @"YES" : @"NO");
      MLogString(@"sourceModel: %@", [[*error userInfo]
    valueForKeyPath:@"sourceModel.entityVersionHashesByName"]);
      MLogString(@"destinationModel: %@", [[*error userInfo]
    valueForKeyPath:@"destinationModel.entityVersionHashesByName"]);
      MLogString(@"reason: %@", [[*error userInfo]
    valueForKeyPath:@"reason"]);

    I have copied the output below. The upshot is that Core Data correctly
    recognizes that there are 2 different models. Il correctly lists the
    entities for each model. Oddly enough it shows twice the same version
    identifier although it should be different. It does nt find the
    migration model although it exists.

    2007-11-01 17:21:10.849 HoudahSpot[1933:10b] Document.m:629
    sourceModel: {(
        "2.0"
    )}
    2007-11-01 17:21:10.850 HoudahSpot[1933:10b] Document.m:630
    destinationModel: {(
        "2.0"
    )}
    2007-11-01 17:21:10.851 HoudahSpot[1933:10b] Document.m:631 same
    model: NO
    2007-11-01 17:21:10.852 HoudahSpot[1933:10b] Document.m:632 equivalent
    model: NO
    2007-11-01 17:21:10.853 HoudahSpot[1933:10b] Document.m:633
    sourceModel: {
        Attribute = <68dbab1b e0e367d6 77b02233 8b70442e bb4322d3
    7fa1aad6 aebf6377 229ea4fb>;
        AttributeValue = <8953cc81 d80ad1a4 c221af0c ef365199 a22a7513
    f3a30496 139946cd 77172c8d>;
        MetaAttribute = <c74fc402 010fec75 10e0c3bf d5ca39a8 7f5bffef
    8ca67089 bb3aa0fa 5fa14144>;
        OrderedScope = <2f9405d0 4a331352 70d9a772 cf3d8629 edd2c033
    11206d72 271d53b8 9bb817e1>;
        QueryItem = <92fb4797 2622383a 99169460 a1458608 6ce3e96b
    1b9e1111 8e6388e4 f5d33bed>;
        QueryLeaf = <78992a6c 7724a71d 21f36dca 9501929a 5ead1066
    b3420239 c520d0ef d748247f>;
        QueryNode = <03de248d fd4198dc 68d33064 5ad79ef3 5a7cbcef
    f376e8a8 512a2834 ddd93037>;
        Scope = <146feb1a 2255255e 174f7ec5 03f003b5 c3ea593a a1baea0d
    b47075c6 b4a9ccff>;
    }
    2007-11-01 17:21:10.854 HoudahSpot[1933:10b] Document.m:634
    destinationModel: {
        Attribute = <68dbab1b e0e367d6 77b02233 8b70442e bb4322d3
    7fa1aad6 aebf6377 229ea4fb>;
        AttributeValue = <8953cc81 d80ad1a4 c221af0c ef365199 a22a7513
    f3a30496 139946cd 77172c8d>;
        ColumnAttribute = <f49ae37f effce04e a6f5f382 b08ab3a2 68a18bc0
    ef8cd598 992e0333 5d62ab38>;
        LimitAttribute = <c1bfbe7f 99537e64 7ffe013b 4d77f015 e02153b7
    ecf3179f c3b8a937 c04e69d0>;
        MetaAttribute = <c74fc402 010fec75 10e0c3bf d5ca39a8 7f5bffef
    8ca67089 bb3aa0fa 5fa14144>;
        OrderedColumnAttribute = <8e062ace 634467a9 7566153c c648d74d
    cc821c3c 2ebc9675 133f79e8 cd1f0368>;
        OrderedExclusionScope = <12732537 2411cfbf 4c8d6dce a46d557a
    d38254fe 008518f9 b70f4755 fb55a12e>;
        OrderedLimitAttribute = <247757f5 24ee13ca c8526e87 2022ede1
    247f3393 cec0083a 14573611 49e2594a>;
        OrderedScope = <2f9405d0 4a331352 70d9a772 cf3d8629 edd2c033
    11206d72 271d53b8 9bb817e1>;
        QueryItem = <92fb4797 2622383a 99169460 a1458608 6ce3e96b
    1b9e1111 8e6388e4 f5d33bed>;
        QueryLeaf = <78992a6c 7724a71d 21f36dca 9501929a 5ead1066
    b3420239 c520d0ef d748247f>;
        QueryNode = <03de248d fd4198dc 68d33064 5ad79ef3 5a7cbcef
    f376e8a8 512a2834 ddd93037>;
        Scope = <146feb1a 2255255e 174f7ec5 03f003b5 c3ea593a a1baea0d
    b47075c6 b4a9ccff>;
    }
    2007-11-01 17:21:10.855 HoudahSpot[1933:10b] Document.m:635 reason:
    Can't find mapping model for migration

    Pierre

    On Nov 1, 2007, at 3:27 PM, Pierre Bernard wrote:

    > Hi!
    >
    > Thanks Malcolm.
    >
    > I got at least one step closer to the solution, still it does not
    > work yet.
    >
    > Here is where I pass the appropriate option to the store coordinator:
    >
    > - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url
    > ofType:(NSString *)fileType
    > modelConfiguration:(NSString *)configuration
    > storeOptions:(NSDictionary *)storeOptions
    > error:(NSError **)error
    > {
    > NSMutableDictionary *options = [NSMutableDictionary
    > dictionaryWithDictionary:storeOptions];
    >
    > [options setObject:[NSNumber numberWithBool:YES]
    > forKey:NSMigratePersistentStoresAutomaticallyOption];
    >
    > BOOL ok = [super configurePersistentStoreCoordinatorForURL:url
    > ofType:fileType
    > modelConfiguration:configuration
    > storeOptions:options
    > error:error];
    >
    > if (*error != nil) {
    > NSLog(@"sourceModel: %@", [[*error userInfo]
    > valueForKeyPath:@"sourceModel.versionIdentifiers"]);
    > NSLog(@"destinationModel: %@", [[*error userInfo]
    > valueForKeyPath:@"destinationModel.versionIdentifiers"]);
    > NSLog(@"same model: %@", ([[*error userInfo]
    > valueForKeyPath:@"sourceModel"] == [[*error userInfo]
    > valueForKeyPath:@"destinationModel"]) ? @"YES" : @"NO");
    > NSLog(@"equivalent model: %@", ([[[*error userInfo]
    > valueForKeyPath:@"sourceModel"] isEqual:[[*error userInfo]
    > valueForKeyPath:@"destinationModel"]]) ? @"YES" : @"NO");
    > NSLog(@"reason: %@", [[*error userInfo] valueForKeyPath:@"reason"]);
    >
    > }
    >
    > return ok;
    > }
    >
    > The problem is that ok == NO. I.e. migration fails and I have no
    > idea where to look for hints or explanations. The error is pretty
    > meaningless except for its userInfo dictionary. Moreover the error
    > is swallowed on the way up to the user where it appears as a generic
    > "cannot open" message.
    >
    > Now what I can't understand is why both source and destination
    > models have the same versionIdentifiers. I guess this would also
    > explain why the mapping model is not found.
    >
    > Best,
    > Pierre
    >
    >
    > On Nov 1, 2007, at 3:23 AM, mmalc crawford wrote:
    >
    >>
    >> On Oct 31, 2007, at 4:00 PM, Pierre Bernard wrote:
    >>
    >>> Does NSPersistentDocument handle versioning issues or do I need to
    >>> hook into document loading to call the migration manager myself?
    >>> What is the recommended approach for using the migration manager
    >>> within the NSDocument architecture?
    >>>
    >> It's just as described here <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataVersionin
    g/Articles/vmInitiating.html
    >> >.
    >>
    >> mmalc
    >>
    >
    > ---
    > Pierre Bernard
    > http://www.bernard-web.com/pierre
    > http://www.houdah.com

    ---
    Pierre Bernard
    http://www.bernard-web.com/pierre
    http://www.houdah.com
  • When you added your model, did you first make your data model a
    "versioned" model?
    When you add new models, if you choose "add new version" it should add
    it to the "versions" without problem.
    **But** If you are adding a "new file" and choose a new data model, it
    will get copied into your apps' resources folder, and you will have
    two models with the same entities etc and cause a conflict.
    Unchecking the checkbox that "includes " the new models in your
    project (get info->targets->uncheck the item) will cause it to not be
    included twice and include it only once in the versioned model...

    Does that work?

    Andre

    On $BJ?@.(B 19/11/02, at 1:23, Pierre Bernard wrote:

    > Now this is odd:
    >
    > I have added some more debugging output.
    >
    > MLogString(@"sourceModel: %@", [[*error userInfo]
    > valueForKeyPath:@"sourceModel.versionIdentifiers"]);
    > MLogString(@"destinationModel: %@", [[*error userInfo]
    > valueForKeyPath:@"destinationModel.versionIdentifiers"]);
    > MLogString(@"same model: %@", ([[*error userInfo]
    > valueForKeyPath:@"sourceModel"] == [[*error userInfo]
    > valueForKeyPath:@"destinationModel"]) ? @"YES" : @"NO");
    > MLogString(@"equivalent model: %@", ([[[*error userInfo]
    > valueForKeyPath:@"sourceModel"] isEqual:[[*error userInfo]
    > valueForKeyPath:@"destinationModel"]]) ? @"YES" : @"NO");
    > MLogString(@"sourceModel: %@", [[*error userInfo]
    > valueForKeyPath:@"sourceModel.entityVersionHashesByName"]);
    > MLogString(@"destinationModel: %@", [[*error userInfo]
    > valueForKeyPath:@"destinationModel.entityVersionHashesByName"]);
    > MLogString(@"reason: %@", [[*error userInfo]
    > valueForKeyPath:@"reason"]);
    >
    >
    > I have copied the output below. The upshot is that Core Data
    > correctly recognizes that there are 2 different models. Il correctly
    > lists the entities for each model. Oddly enough it shows twice the
    > same version identifier although it should be different. It does nt
    > find the migration model although it exists.
    >
    > 2007-11-01 17:21:10.849 HoudahSpot[1933:10b] Document.m:629
    > sourceModel: {(
    > "2.0"
    > )}
    > 2007-11-01 17:21:10.850 HoudahSpot[1933:10b] Document.m:630
    > destinationModel: {(
    > "2.0"
    > )}
    > 2007-11-01 17:21:10.851 HoudahSpot[1933:10b] Document.m:631 same
    > model: NO
    > 2007-11-01 17:21:10.852 HoudahSpot[1933:10b] Document.m:632
    > equivalent model: NO
    > 2007-11-01 17:21:10.853 HoudahSpot[1933:10b] Document.m:633
    > sourceModel: {
    > Attribute = <68dbab1b e0e367d6 77b02233 8b70442e bb4322d3
    > 7fa1aad6 aebf6377 229ea4fb>;
    > AttributeValue = <8953cc81 d80ad1a4 c221af0c ef365199 a22a7513
    > f3a30496 139946cd 77172c8d>;
    > MetaAttribute = <c74fc402 010fec75 10e0c3bf d5ca39a8 7f5bffef
    > 8ca67089 bb3aa0fa 5fa14144>;
    > OrderedScope = <2f9405d0 4a331352 70d9a772 cf3d8629 edd2c033
    > 11206d72 271d53b8 9bb817e1>;
    > QueryItem = <92fb4797 2622383a 99169460 a1458608 6ce3e96b
    > 1b9e1111 8e6388e4 f5d33bed>;
    > QueryLeaf = <78992a6c 7724a71d 21f36dca 9501929a 5ead1066
    > b3420239 c520d0ef d748247f>;
    > QueryNode = <03de248d fd4198dc 68d33064 5ad79ef3 5a7cbcef
    > f376e8a8 512a2834 ddd93037>;
    > Scope = <146feb1a 2255255e 174f7ec5 03f003b5 c3ea593a a1baea0d
    > b47075c6 b4a9ccff>;
    > }
    > 2007-11-01 17:21:10.854 HoudahSpot[1933:10b] Document.m:634
    > destinationModel: {
    > Attribute = <68dbab1b e0e367d6 77b02233 8b70442e bb4322d3
    > 7fa1aad6 aebf6377 229ea4fb>;
    > AttributeValue = <8953cc81 d80ad1a4 c221af0c ef365199 a22a7513
    > f3a30496 139946cd 77172c8d>;
    > ColumnAttribute = <f49ae37f effce04e a6f5f382 b08ab3a2 68a18bc0
    > ef8cd598 992e0333 5d62ab38>;
    > LimitAttribute = <c1bfbe7f 99537e64 7ffe013b 4d77f015 e02153b7
    > ecf3179f c3b8a937 c04e69d0>;
    > MetaAttribute = <c74fc402 010fec75 10e0c3bf d5ca39a8 7f5bffef
    > 8ca67089 bb3aa0fa 5fa14144>;
    > OrderedColumnAttribute = <8e062ace 634467a9 7566153c c648d74d
    > cc821c3c 2ebc9675 133f79e8 cd1f0368>;
    > OrderedExclusionScope = <12732537 2411cfbf 4c8d6dce a46d557a
    > d38254fe 008518f9 b70f4755 fb55a12e>;
    > OrderedLimitAttribute = <247757f5 24ee13ca c8526e87 2022ede1
    > 247f3393 cec0083a 14573611 49e2594a>;
    > OrderedScope = <2f9405d0 4a331352 70d9a772 cf3d8629 edd2c033
    > 11206d72 271d53b8 9bb817e1>;
    > QueryItem = <92fb4797 2622383a 99169460 a1458608 6ce3e96b
    > 1b9e1111 8e6388e4 f5d33bed>;
    > QueryLeaf = <78992a6c 7724a71d 21f36dca 9501929a 5ead1066
    > b3420239 c520d0ef d748247f>;
    > QueryNode = <03de248d fd4198dc 68d33064 5ad79ef3 5a7cbcef
    > f376e8a8 512a2834 ddd93037>;
    > Scope = <146feb1a 2255255e 174f7ec5 03f003b5 c3ea593a a1baea0d
    > b47075c6 b4a9ccff>;
    > }
    > 2007-11-01 17:21:10.855 HoudahSpot[1933:10b] Document.m:635 reason:
    > Can't find mapping model for migration
    >
    >
    > Pierre
    >
    >
    > On Nov 1, 2007, at 3:27 PM, Pierre Bernard wrote:
    >
    >> Hi!
    >>
    >> Thanks Malcolm.
    >>
    >> I got at least one step closer to the solution, still it does not
    >> work yet.
    >>
    >> Here is where I pass the appropriate option to the store coordinator:
    >>
    >> - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url
    >> ofType:(NSString *)fileType
    >> modelConfiguration:(NSString *)configuration
    >> storeOptions:(NSDictionary *)storeOptions
    >> error:(NSError **)error
    >> {
    >> NSMutableDictionary *options = [NSMutableDictionary
    >> dictionaryWithDictionary:storeOptions];
    >>
    >> [options setObject:[NSNumber numberWithBool:YES]
    >> forKey:NSMigratePersistentStoresAutomaticallyOption];
    >>
    >> BOOL ok = [super configurePersistentStoreCoordinatorForURL:url
    >> ofType:fileType
    >> modelConfiguration:configuration
    >> storeOptions:options
    >> error:error];
    >>
    >> if (*error != nil) {
    >> NSLog(@"sourceModel: %@", [[*error userInfo]
    >> valueForKeyPath:@"sourceModel.versionIdentifiers"]);
    >> NSLog(@"destinationModel: %@", [[*error userInfo]
    >> valueForKeyPath:@"destinationModel.versionIdentifiers"]);
    >> NSLog(@"same model: %@", ([[*error userInfo]
    >> valueForKeyPath:@"sourceModel"] == [[*error userInfo]
    >> valueForKeyPath:@"destinationModel"]) ? @"YES" : @"NO");
    >> NSLog(@"equivalent model: %@", ([[[*error userInfo]
    >> valueForKeyPath:@"sourceModel"] isEqual:[[*error userInfo]
    >> valueForKeyPath:@"destinationModel"]]) ? @"YES" : @"NO");
    >> NSLog(@"reason: %@", [[*error userInfo]
    >> valueForKeyPath:@"reason"]);
    >>
    >> }
    >>
    >> return ok;
    >> }
    >>
    >> The problem is that ok == NO. I.e. migration fails and I have no
    >> idea where to look for hints or explanations. The error is pretty
    >> meaningless except for its userInfo dictionary. Moreover the error
    >> is swallowed on the way up to the user where it appears as a
    >> generic "cannot open" message.
    >>
    >> Now what I can't understand is why both source and destination
    >> models have the same versionIdentifiers. I guess this would also
    >> explain why the mapping model is not found.
    >>
    >> Best,
    >> Pierre
    >>
    >>
    >> On Nov 1, 2007, at 3:23 AM, mmalc crawford wrote:
    >>
    >>>
    >>> On Oct 31, 2007, at 4:00 PM, Pierre Bernard wrote:
    >>>
    >>>> Does NSPersistentDocument handle versioning issues or do I need
    >>>> to hook into document loading to call the migration manager myself?
    >>>> What is the recommended approach for using the migration manager
    >>>> within the NSDocument architecture?
    >>>>
    >>> It's just as described here <http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataVersionin
    g/Articles/vmInitiating.html
    >>> >.
    >>>
    >>> mmalc
    >>>
    >>
    >> ---
    >> Pierre Bernard
    >> http://www.bernard-web.com/pierre
    >> http://www.houdah.com
    >
    > ---
    > Pierre Bernard
    > http://www.bernard-web.com/pierre
    > http://www.houdah.com
  • Hi Malcom!

    Thanks a bunch. This really helped a lot!

    There however seems to be a problem with my 1.0 files created under
    Tiger. These files have no versioning information in their metadata.
    Thus I had to resort to manual migration for those files. Guess that
    ought to be documented.

    The only remaining problem I have is that for an odd reason the
    migrated file is opened as "File.hspt~" rather than just "File.hspt"
    which causes unwanted behavior on save later on. Any ideas how this
    comes about?

    Best,
    Pierre

    - (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url
                                             ofType:(NSString *)fileType
                                 modelConfiguration:(NSString *)configuration
                                        storeOptions:(NSDictionary *)storeOptions
              error:(NSError **)error
    {
    NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator
    metadataForPersistentStoreOfType:NSSQLiteStoreType URL:url error:error];

    if (sourceMetadata == nil)
    {
      return NO;
    }

    id versionHashes = [sourceMetadata
    objectForKey:@"NSStoreModelVersionHashes"];
    BOOL ok = NO;

    if (versionHashes != nil) {
      NSMutableDictionary *newStoreOptions;

      if (storeOptions == nil)
      {
      newStoreOptions = [NSMutableDictionary dictionary];
      }
      else
      {
      newStoreOptions = [[storeOptions mutableCopy] autorelease];
      }

      [newStoreOptions setObject:[NSNumber numberWithBool:YES]
    forKey:NSMigratePersistentStoresAutomaticallyOption];

      ok = [super configurePersistentStoreCoordinatorForURL:url
                                                         ofType:fileType
                                             modelConfiguration:configuration
                                                    storeOptions:newStoreOptions
                  error:error];
    }
    else {
      NSURL *modelURL = [NSURL fileURLWithPath:[Document
    pathForModelNamed:@"HoudahSpot"]];
      NSManagedObjectModel *sourceModel = [[NSManagedObjectModel alloc]
    initWithContentsOfURL:modelURL];

      NSManagedObjectModel *destinationModel = [self managedObjectModel];


      /*
            To perform the migration, we also need a mapping model.
            We have the source and destination model; NSMapping model provides
    a convenience method to find the correct mapping model from a given
    array of bundles.
            */

      NSArray *bundles = [NSArray arrayWithObject:[NSBundle mainBundle]];

      NSMappingModel *mappingModel = [NSMappingModel
    mappingModelFromBundles:bundles forSourceModel:sourceModel
    destinationModel:destinationModel];

      if (mappingModel == nil)
      {
      // should create a suitable NSError and set in 'error'
      return NO;
      }

      /*
            Move the legacy file out of the way
            */
      NSString *originalPath = [url path];
      NSString *legacyPath = [NSString stringWithFormat:@"%@~",
    originalPath];
      BOOL success = [[NSFileManager defaultManager] movePath:originalPath
    toPath:legacyPath handler:nil];

      if (!success) {
      return NO;
      }

      NSURL *sourceURL = [NSURL fileURLWithPath:legacyPath isDirectory:NO];
      NSURL *destinationURL = [NSURL fileURLWithPath:originalPath
    isDirectory:NO];

      /*
            Create the migration manager and perform the migration
            */

      NSMigrationManager *migrationManager = [[NSMigrationManager alloc]
    initWithSourceModel:sourceModel destinationModel:destinationModel];

      ok = [migrationManager migrateStoreFromURL:sourceURL
    type:NSSQLiteStoreType options:storeOptions
    withMappingModel:mappingModel toDestinationURL:destinationURL
    destinationType:NSSQLiteStoreType destinationOptions:storeOptions
    error:error];

      [migrationManager release];

      if (!ok)
      {
      return NO;
      }

      /*
            Add the new store to the store coordinator and set the file URL
            */
      NSPersistentStoreCoordinator *psc = [[self managedObjectContext]
    persistentStoreCoordinator];

      NSPersistentStore *destinationStore = [psc
    addPersistentStoreWithType:NSSQLiteStoreType
    configuration:configuration URL:destinationURL options:storeOptions
    error:error];

      if (destinationStore == nil)
      {
      return NO;
      }

      [self setFileURL:destinationURL];
    }

    if (ok)
    {
      /*
            If all went well, update the metadata
            */
      NSPersistentStoreCoordinator *psc = [[self managedObjectContext]
    persistentStoreCoordinator];

      id pStore = [psc persistentStoreForURL:[self fileURL]];

      /*
            configurePersistentStoreCoordinatorForURL is called when document
    reopened
            Check for existing metadata to avoid overwriting unnecessarily
            */
      id existingMetadata = [[psc metadataForPersistentStore:pStore]
    objectForKey:(NSString *)kMDItemKeywords];

      if (existingMetadata == nil)
      {
      if (![self setMetadataForStoreAtURL:[self fileURL]])
      {
        return NO;
      }
      }
    }

    return ok;
    }

    On Nov 2, 2007, at 6:53 AM, mmalc crawford wrote:

    > >.
    >
    > mmalc
    >

    ---
    Pierre Bernard
    http://www.bernard-web.com/pierre
    http://www.houdah.com
  • On Nov 2, 2007, at 8:53 AM, Pierre Bernard wrote:

    > There however seems to be a problem with my 1.0 files created under
    > Tiger. These files have no versioning information in their metadata.
    > Thus I had to resort to manual migration for those files. Guess that
    > ought to be documented.
    >
    Indeed.  I'm sure this and in particular the no-custom-classes issue
    were documented at some stage.  I don't know where those paragraphs
    went  :-(

    > The only remaining problem I have is that for an odd reason the
    > migrated file is opened as "File.hspt~" rather than just "File.hspt"
    > which causes unwanted behavior on save later on. Any ideas how this
    > comes about?
    >
    Hmm, no.  Generally NSPersistentDocument doesn't seem very happy with
    the original implementation.  I've created an updated version that
    uses a subclass of NSDocumentController to perform the migration: <http://homepage.mac.com/mmalc/CocoaExamples/controllers.html>.  I still don't think it's ideal, but thus far it seems better than
    the original.  I'll let you know if it changes significantly again.

    mmalc
  • On Nov 6, 2007, at 9:03 PM, mmalc crawford wrote:

    > Hmm, no.  Generally NSPersistentDocument doesn't seem very happy
    > with the original implementation.  I've created an updated version
    > that uses a subclass of NSDocumentController to perform the
    > migration: <http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
    > >.  I still don't think it's ideal, but thus far it seems better
    > than the original.  I'll let you know if it changes significantly
    > again.
    >
    I've "played around" with this a little more.  It now does a fair
    amount of error checking etc. as well.  NSDocumentController does seem
    to be the easiest place to deal with this...  In particular, it now
    checks that you don't already have an existing file at the
    destination, an if you do (subject to user acceptance) it deletes it.
    Otherwise Core Data would simply append to the existing file.
    Feedback would be welcome (please send off-list).

    mmalc
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today