Co muszę zrobić, aby dane podstawowe mogły automatycznie migrować modele?


96

Przeczytałem dokumentację dotyczącą automatycznej / lekkiej migracji modeli Core Data - ale mam problemy z jej wdrożeniem.

Jak rozumiem, aplikacja powinna zauważyć, że model, który ma, i model, który już istnieje na urządzeniu, nie są tym samym. Jeśli dodałeś tylko atrybuty lub relacje i podobne proste zmiany, model powinien zostać zaktualizowany automatycznie.

Wszelkie wskazówki - czy muszę coś ustawić w Xcode?

Odpowiedzi:


138

Teraz odkryłem, że jest to dość proste - kiedy już wiesz, gdzie szukać.

W moim AppDelegate konfiguruję NSPersistentStoreCoordinator - i musisz dodać do tego kilka opcji, aby nakazać mu obsługę automatycznej migracji:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

Następnie musisz zrobić małą sztuczkę w xCode:

  1. Wybierz plik xcdatamodel
  2. Wybierz menu Projekt u góry - następnie Model danych - a następnie wybierz Dodaj wersję modelu
  3. Twój plik xcdatamodel zostanie następnie przeniesiony do nowego katalogu o takiej samej nazwie jak plik xcdatamodel, ale z rozszerzeniem xcdatamodeld - w tym katalogu będzie drugi plik z 2 w nazwie. Wybierz nowy plik, a następnie Projekt-> Model danych-> Ustaw bieżącą wersję ( w Xcode 4 robisz to )
  4. Jeśli wprowadziłeś już zmiany, które spowodowały niezgodność projektu - usuń te zmiany z oryginalnego pliku xcdatamodel. Jeśli jeszcze nie wprowadziłeś zmian - po prostu edytuj plik 2.xcdatamodel (ten, który właśnie wprowadziłeś w bieżącej wersji).
  5. Teraz, gdy zainstalujesz tę wersję na urządzeniu, które ma stary model - automatycznie zaktualizuje ten model do nowego modelu.

Wydaje się to świetne i tak proste, jak chciałem - ale myślę, że podczas programowania przy zmianie modelu trzeba zachować ostrożność - w przeciwnym razie będziesz musiał stworzyć nową wersję dla każdej zmiany.

Myślę, że zachowam wszystkie zmienione pliki, a gdy będę gotowy do wdrożenia aktualizacji, usunę wszystkie pliki pośrednie i po prostu wdrożę z najstarszymi i najnowszymi modelami.


AKTUALIZACJA (15/07/2011):

Podziękowania dla @ rockstarberlin za wskazanie, że w Apple jest zaktualizowana dokumentacja:

Xcode 4: Ustawianie bieżącej wersji zarządzanego modelu obiektów

Aktualizacja: 19.08.2013 lepszy link:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html


Sugeruję przeczytanie przewodnika po migracji i wersjonowaniu podstawowych danych, dostępnego w przeglądarce dokumentów Xcode i na developer.apple.com.
Hunter

1
Nie znalazłem tam odpowiedzi po prostu - zajęło trochę czasu, zanim dowiedziałem się, jak to zrobić.
Grouchal

NSInferMappingModelAutomaticallyOption działa dobrze, ale tylko w przypadku prostych mapowań, takich jak zmiana nazwy atrybutu. W przypadku czegoś bardziej skomplikowanego (relacje, usuwanie lub dodawanie jednostek) będziesz musiał dodać model mapowania. Jeśli Xcode zgłasza skargę, że NSInferMappingModelAutomaticallyOption jest niezadeklarowana, dodaj #import <CoreData / CoreData.h> do pliku nagłówka delegata aplikacji.
Elise van Looij

Dodałem kilka encji do mojego modelu i otrzymałem niesławny błąd „Model użyty do otwarcia sklepu jest niezgodny z tym, który został użyty do utworzenia sklepu”. Twoje rozwiązanie to naprawiło! Dziękuję Ci bardzo!
Karsten Silz

1
Zobacz odpowiedź Santthosha poniżej, jeśli po wykonaniu tych instrukcji pojawia się błąd „nie można scalić modeli z dwoma różnymi obiektami o nazwie”.
benvolioT

14

To było niezwykle pomocne. Dokumentacja Apple była - jak zwykle - żałośnie niekompletna. Zalecam wykonanie czystej kompilacji, ponieważ napotkałem błąd „Nie można scalić modeli z dwoma różnymi encjami xxx” podczas pierwszego uruchomienia po wprowadzeniu tych zmian. Czysta kompilacja naprawiła to.


Czysta kompilacja rozwiązała również moje problemy.
jrainbow

6

Odpowiedź Grouchala jest idealna ... ale jeśli nadal masz komunikat „Nie można scalić modeli z dwoma różnymi obiektami xxx”, nawet po kilkukrotnym wyczyszczeniu kompilacji ... Możesz mieć problemy z ładowaniem managedObjectModel .. . spójrz na ten ... który pomógł mi to naprawić ..

podstawowe problemy z migracją danych


3

Ponadto, jeśli natknąłeś się na ten post, tak jak ja, po otrzymaniu błędu „Model użyty do otwarcia sklepu jest niezgodny z tym, który został użyty do utworzenia sklepu” i po prostu debugujesz za pomocą symulatora i chcesz całkowicie zastąpić zainstalowany stary model, możesz po prostu zresetować aplikację Simulator lub usunięcie aplikacji z symulatora prawdopodobnie również zadziała.

Nie przyszło mi do głowy, żebym spróbował tego, dopóki nie przeczytałem tutaj postów, w którym to momencie zdałem sobie sprawę, że zainstalowałem aplikację w symulatorze, a następnie zmieniłem model, powodując wspomniany powyżej błąd czasu wykonywania.


1

Aby śledzić odpowiedź Santthosha, pomyślałem, że zamiast tego opublikuję fragment kodu tutaj. Musisz utworzyć managedObjectModel za pomocą initWithContentsOfURL:zamiast w mergedModelFromBundles:przeciwnym razie pojawi się błąd:

Nie można scalić modeli z dwoma różnymi jednostkami XXX i XXX

Jeśli plik modelu nosi nazwę „Model”, oto jak utworzyć managedObjectModel:

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

Podziękowania dla tego posta na blogu .



1

Mam ten problem od lat i bezskutecznie wypróbowałem wszystkie te odpowiedzi. Dzisiaj w końcu zorientowałem się, co robię źle. Bardzo prosty problem, ale go przeoczyłem. Tworząc nowszą wersję modelu danych, jeśli DODAWASZ kolumny, pamiętaj, aby oznaczyć je jako OPCJONALNE. Jeśli tego nie zrobisz, prosta migracja nie zadziała, ponieważ nowe wartości kolumn nie zostaną wypełnione.

Gdy tylko upewniłem się, że moje nowe kolumny są zaznaczone jako „opcjonalne”, spróbowałem ponownie przeprowadzić migrację i zadziałało.


1

Natknąłem się na ten post z powodu innych problemów, ale błąd brzmiał: „ Modelowa konfiguracja użyta do otwarcia sklepu jest niekompatybilna z tą, która została użyta do utworzenia sklepu ”.

Oto mój problem i jego rozwiązanie. W moim modelu korzystałem z konfiguracji . Niektóre elementy były przechowywane w jednym pliku, a inne w drugim. (Mam pewne ustawienia domyślne, które mogą wymagać okresowego pobierania, a scalenie ich w całość byłoby niewiarygodnym problemem). W każdym razie stworzyłem nową jednostkę. Program wydawał się działać dobrze, ale za każdym razem, gdy kończyłem, otrzymywałem powyższy błąd.

Rozwiązaniem było przyjrzenie się moim konfiguracjom, uświadomienie sobie, że miałem jednostkę, której nie było obecnie w żadnej z konfiguracji i dodanie jej do jednej. Działa jak sen.

To nie rozwiąże problemu OP. Ale może jakaś sfrustrowana osoba, która wyląduje tutaj przez Google, będzie w łodzi, na której byłem :)


0

iOS 4.0+

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

0

Niewielka edycja niesamowitych instrukcji @ Grouchal powyżej dla Xcode w wersji 5:

Stare: 2. Wybierz menu Projekt u góry - następnie Model danych - a następnie wybierz Dodaj wersję modelu

Wersja 5+: 2. Wybierz menu Edytor, a następnie Dodaj wersję modelu…, wpisz nazwę swojej wersji i Na podstawie modelu (wybierz swój oryginalny model z listy)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.