How to edit a NSManagedObjectModel that was loaded

2019-04-02 01:10发布

问题:

For my iOS application using CoreData, I need to have a model where certain entities properties vary between the iPhone and iPad version of the app. To achieve this, I load a NSManagedObjectModel from a momd file located in my application bundle, using initWithContentsOfURL: . But, before the model is actually used by the storeCoordinator, I modify some entities programmatically in the model (based on information I store in a device specific plist). This used to work flawlessly on iOS4. As Apple states in its documentation,

Managed object models are editable until they are used by an object graph manager (a managed object context or a persistent store coordinator).

This does not seem to be the case in iOS5 anymore (although the documentation still states this). As soon as the model is created, with initWithContentsOfURL: for example, any attempt to modify throws an 'NSInternalInconsistencyException', reason: 'Can't modify an immutable model.' If I print the description of the model object in the debugger just after it was created, it reads 'isEditable 0', where the same reads 'isEditable 1' when running the same code on iOS4.

Using "copy" on the model the create an editable copy, as suggested by Apple, also returns a model with "isEditable 0".

I see two potential explanations for this :

  • Bug . I couldn't find a matching bugreport on openradar, I will file one if necessary.
  • iCloud integration. I'm not very familiar with iCloud APIs yet, but I know some kind of integration with CoreData can be set up. I imagine that maybe some automatic coordinator could access my model at the time it's created, rendering it uneditable.

I'll continue digging into these options, but if anybody has experience with this, it would be greatly appreciated.

回答1:

I filed a radar on this very issue on Oct 5 and received the following response today:

You can get a mutable copy of the model by calling -mutableCopy on the NSManagedObjectModel instance.

This worked on the iOS 5 simulator, I haven't yet tested on a device. Didn't try that myself because NSManagedObjectModel doesn't conform to NSMutableCopying (according to the documentation), and the header file doesn't mention -(id)mutableCopy.

I had worked around it back in October by creating a fresh NSManagedObjectModel by merging the one from the momd file with an empty NSManagedObjectModel. I suppose the models from momd files now are internally immutable, but the others (from copy or merge) are actually mutable.



回答2:

It's a bug or an undocumented change. I ran this test code:

  NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestManageObjectModelEdits" withExtension:@"momd"];
  NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
  NSEntityDescription *e=[[NSEntityDescription alloc] init];
  [e setName:@"PEntity"];
  NSArray *a=[mom entities];
  NSArray *b=[a arrayByAddingObject:e];
  [mom setEntities:b];
  NSLog(@"mom = %@",mom);

… under iOS 4.3 and 5.0. It works under 4.3 and throws an error saying it can't modify the model file under 5.0.