Próbuję wykonać lekką migrację sklepu SQLite w Core Data. Praca nad Lion 10.7.3 z Xcode 4.3.1.
W mojej podklasie NSPersistentDocument (AccountDocument) nadpisałem metodę używaną do skonfigurowania trwałego koordynatora magazynu, aby uzyskać odpowiednie opcje migracji:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newStoreOptions;
if (storeOptions == nil) {
newStoreOptions = [NSMutableDictionary dictionary];
}
else {
newStoreOptions = [storeOptions mutableCopy];
}
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
return result;
}
(Podziękowania dla Malcolma Crawforda za tę wskazówkę:http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)
Kiedy uruchamiam aplikację, kończy się niepowodzeniem w implementacji NSPersistentDocument-managedObjectModel
:
* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298
Z tego, co mogę powiedzieć z dokumentacji, domyślna implementacja wygląda mniej więcej tak:
- (id)managedObjectModel
{
NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
return result;
}
Aby nieco bardziej zdebugować problem, zastąpiłem tę metodę następującą:
- (id)managedObjectModel
{
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];
return result;
}
(Podziękowania dla Jeffa LaMarche za pomysł:http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html)
Pakiet i adres URL wskazują miejsca, których się spodziewam (i postępowałem zgodnie z radą Marcusa Zarry, aby wyczyścić projekt, aby w pakiecie aplikacji nie było żadnych zbłąkanych pakietów .mom ani .momd:Korzystanie z scaledModelFromBundles: i wersjonowania (CoreData)). Jednak aplikacja nadal ulega awarii podczas ładowania modelu z adresu URL.
Sprawdziłem, czy AccountDocument2.xcdatamodeld to pakiet, który ma dwa modele do wersjonowania: AccountDocument 2.xcdatamodel i (oryginalny) AccountDocument.xcdatamodel. Menu podręczne „Wersjonowany podstawowy model danych” we właściwościach pliku jest ustawione na „Dokument konta 2”.
Jedyną różnicą między tymi dwoma modelami jest to, że jedna jednostka ma dodatkowy (i opcjonalny) atrybut. Rozumiem, że model kwalifikuje się do lekkiej migracji.
Oczywiście robię tu coś nie tak, ale nie mam pojęcia, co. Każda pomoc będzie mile widziana…
Aktualizacja:
Zgodnie z sugestią Martina (i sprawdzeniem dokumentacji NSPersistentDocument) próbowałem użyć tego kodu dla akcesora:
- (id)managedObjectModel
{
static id sharedManagedObjectModel = nil;
if (sharedManagedObjectModel == nil) {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
}
return sharedManagedObjectModel;
}
Nadal się zawiesza…
Aktualizacja
Po kilku sugestiach na Twitterze dokonałem aktualizacji do Xcode 4.3.2, ale problemy nadal występują.
RAGE UPDATE
Właśnie utworzyłem wersjonowany pakiet modelu (AccountDocument2.xcdatamodeld) przy użyciu Xcode 4.2 w systemie Snow Leopard. Po zbudowaniu i uruchomieniu aplikacji wszystko działa zgodnie z oczekiwaniami.
Następnie wziąłem pakiet plików AccountDocument2.xcdatamodeld z powrotem do Lion i Xcode 4.3.2. Kiedy tworzę i uruchamiam aplikację, nadal ulega awarii podczas ładowania zasobu .momd. Tak, dzieciaki, oznacza to, że Xcode 4.3.x i Data Model Compiler (MOMC) są winne. Nie widzę innego rozwiązania niż wykonanie wszystkich moich kompilacji w systemie Snow Leopard.
Nie jestem osobą, która atakuje Xcode 4, ale kiedy znajdujemy się w sytuacji, w której łańcuch narzędzi nie może utworzyć nieprzezroczystego pliku (.mom i .momd) z nieprzezroczystej specyfikacji (.xcdatamodel i .xcdatamodeld), jest to dość trudne bądź optymistyczny, jeśli chodzi o stan narzędzi dla komputerów Mac i iOS. To śmieszne, że podstawowy komponent tych platform psuje się do tego stopnia, że nie mogę zbudować i uruchomić mojej aplikacji na najnowszej wersji zestawu SDK i narzędzi programistycznych.
Nadchodzi ta aktualizacja
Więcej dowodu na to, że jest to poważny błąd w kompilatorze modelu danych (MOMC) w Xcode 4.3.2: jeśli skopiuję pakiet .momd z folderu zasobów utworzonego przez Xcode 4.2 do mojego projektu i dodam je do kompilacji jako plik Copy Files w fazie budowania, aplikacja działa dobrze.
Zrobiłem również kilka testów, w których usunąłem reguły walidacji i domyślne wartości dla atrybutów różnych jednostek (na podstawie sugestii Marcusa poniżej). Bez zmian, kompilator nadal tworzy nieprawidłowy plik .momd. Próbowałem również stworzyć wersjonowany model, w którym NIC nie zostało zmienione: skompilowany plik .momd nadal się zawieszał. Więc to, co masz w swoich aktualnych modelach (i danych, które reprezentują) jest źródłem problemu.
Uwaga: ten błąd nie jest izolowany do NSPersistentDocument (tak jak pierwotnie myślałem, kiedy zacząłem to pytanie). Mogę spowodować awarię aplikacji, używając po prostu[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]
.
Na razie będę edytować / wersjonować moje modele przy użyciu Xcode 4.2 w systemie Snow Leopard i przenosić skompilowane zasoby do Xcode 4.3.2 na Lion. Jeśli używasz danych podstawowych w jakikolwiek sposób, sugeruję, abyś robił to samo, dopóki ten błąd nie zostanie naprawiony. Zaufaj mi, spędzisz dni próbując dowiedzieć się, co się dzieje, jeśli tego nie zrobisz.
Teraz przesyłam radar…
Aktualizacja radaru
Właśnie przesłałem ten radar:
http://www.openradar.me/11184500
Aktualizacja o cholera, to musi być lew
Właśnie pobrałem i zainstalowałem Xcode 4.2 dla narzędzi Lion z witrynyhttp://developer.apple.com/downloads. Przykładowa aplikacja używana w Radar nadal ulega awarii.
(Uwaga: nie można zainstalować Xcode 4.2.1, ponieważ certyfikat użyty do podpisania DeveloperTools.pkg wygasł. Tylko Xcode 4.2 będzie działać).
Jeśli jesteś objęty umową o zachowaniu poufności, przekonasz się również, że narzędzia beta również nie są pomocne.
Mam nadzieję, że masz kopię Snow Leopard z Xcode 4.2 w pobliżu:http://furbo.org/2012/03/28/vmware-for-developers/
Żądania pobrania WTF muszą zrobić z wersjonowanymi jednostkami i aktualizacją atrybutów
Via Evadne Wu na Twitterze:
https://twitter.com/#!/evadne/status/187625192342818818
I jak to zrobiła:
https://twitter.com/#!/evadne/status/187629091518816258
(pliki .mom to binarne pliki plists.)
Źródłem problemu jest pojedyncze żądanie pobrania. Inżynier z Apple powinien dowiedzieć się, w jaki sposób wpływa to na migrację danych z jednego modelu do drugiego.
Wszystkie odpowiedzi
Skompilowane zasoby .momd można załadować po zmianie żądania pobierania „existingPartner” z:
do:
Jest sprzeczne z intuicją, że część modelu obiektowego, która nie wpływa na trwałość danych, przerywa wersjonowanie i uproszczoną migrację. Z dokumentacji jasno wynika, że tak nie powinno być:
Wykorzystaj mocBLOKADAaby naprawić Żądania pobierania lub całkowicie je usunąć i polegać na nichNSPredicates utworzone w kodzie.
Myślę, że musisz przechowywać zarządzany model obiektów w zmiennej instancji. Zwracasz obiekt z autouzyskiwania, co prawdopodobnie powoduje zły dostęp.
Opierając się na twojej teorii, że jest to problem z MOMC, czy masz jakieś zasady walidacji u mamy?
Widziałem raporty, w których reguły walidacji nie przetrwały MOMC 4.x.
Może to być nieco związane z problemem, który miałem z korzystaniem z żądań pobierania, gdy iOS5 po raz pierwszy pojawił się w wersji beta. Powoduje to ostrzeżenie o kompilacji i powoduje awarię aplikacji podczas uruchamiania. Tak naprawdę nie korzystałem z żądania pobierania, więc je usunąłem i wszystko działało dobrze:Ostrzeżenie dotyczące podstawowych danych: „Informacje o skrótach wersji nie są dostępne dla wszystkich modeli”
Leave a Reply