2012-06-23 20 views
15

sto caricando un modello NSManagedObjectModel con l'initWithContentsOfURL: costruttore in questo modo:Caricare un modello precedente versione

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

Tuttavia questo mi dà solo l'accesso alla versione più recente/attuale di un modello. È possibile caricare versioni precedenti con lo stesso file momd? Come?

risposta

32

In realtà è possibile caricare una versione precedente con:

- (NSManagedObjectModel *)managedObjectModelForVersion:(NSString *)version 
{ 
     NSURL *modelURL = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:@"AppModel.momd/AppModel %@",version] withExtension:@"mom"]; 
     NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
     return model; 
} 

Basta sostituire AppModel con il nome del modello.

Lo sto utilizzando per uscire da una situazione di migrazione manuale che coinvolge iCloud. Ricercato in alto e in basso e non riuscivo a trovarlo da nessuna parte.

+0

fyi sulla mia versione (7.1) la versione .mom (s) sono in un file con lo stesso nome della versione (quindi @ "... /% @", versione anziché @ "/.../ AppModel% @ ", versione) –

-2

No, non è previsto che ciò sia possibile. Deduco che dal NSManagedObjectModeldocumentation, in cui si dice discutere la proprietà versionIdentifiers:

Questo valore è destinato a essere usato come un suggerimento di debug per aiutare a determinare i modelli che sono stati combinati per creare un modello di fusione.

Quindi non sembra che si supponga di utilizzare versioni precedenti del modello per la logica del programma.

+0

come si fa normalmente una migrazione personalizzata? per risolvere temporaneamente questo, faccio una copia della cartella per il mio modello di dati (che contiene di nuovo tutte le versioni) e imposta come versione di default quella più vecchia che voglio supportare. In questo modo posso creare le vecchie e nuove istanze di NSManagedObjectModel di cui ho bisogno per NSMigrationManager – SystematicFrank

+0

Non sono d'accordo con questo. Si prega di vedere la mia risposta. – Schoob

3

Se si desidera solo per caricare la versione del modello che è compatibile con un particolare negozio prova esistente:

NSError *error = nil; 
NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType 
                         URL:storeURL 
                         error:&error]; 
NSManagedObjectModel *oldManagedObjectModel = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]] 
                      forStoreMetadata:storeMetadata]; 

Si noti che se si utilizza la versione XCode identificatori per le versioni del modello dei dati, la versione corrente del negozio permanente gli identificatori sono accessibili tramite la voce NSStoreModelVersionIdentifiersKey nel dizionario dei metadati del negozio.

Per quanto riguarda il caricamento di una particolare versione arbitraria, i file mom si trovano in genere nella directory momd nel bundle dell'app, quindi è possibile enumerarli utilizzando NSFileManager. Credo di trovarne uno con un identificatore di versione particolare che dovresti usare initWithContentsOfURL di NSManagedObjectModel: inizializzatore e poi ispezionare la proprietà versionIdentifiers, o usare isConfiguration: compatibleWithStoreMetadata: metodo di istanza per determinare la compatibilità.

+0

E verificare un nil storeMetadata nel qual caso non si dispone di un database esistente, quindi è necessario crearne uno! –

2

Creato il solution offerto da @Schoob in una categoria, perché si oscilla.

@interface NSManagedObjectModel (version) 
+ (NSManagedObjectModel *)modelFromBundle:(NSBundle *)bundle name:(NSString *)modelName version:(NSString *)version; 
@end 

@implementation NSManagedObjectModel (version) 
+ (NSManagedObjectModel *)modelFromBundle:(NSBundle *)bundle name:(NSString *)modelName version:(NSString *)version 
{ 
    if(!bundle) 
     bundle = [NSBundle mainBundle]; 

    NSString *resource = [[modelName stringByAppendingPathExtension:@"momd"] stringByAppendingPathComponent:version]; 
    NSURL *modelURL = [bundle URLForResource:resource withExtension:@"mom"]; 
    NSAssert(modelURL,@"Unable to find MOM - %@",resource); 
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
    NSAssert(model,@"Unable to load MOM at URL- %@",modelURL); 
    return model; 
} 
@end 
0

Versione Swift. Sostituisci il nome del file.

import CoreData 

extension NSManagedObjectModel 
{ 
    class func model(forVersion version: Int) -> NSManagedObjectModel? 
    { 
     if let fileUrl = Bundle.main.url(forResource: "Model.momd/Model \(version)", withExtension: "mom") 
     { 
      return NSManagedObjectModel(contentsOf: fileUrl) 
     } 
     return .none 
    } 
} 
Problemi correlati