ฉันต้องทำอย่างไรเพื่อให้ Core Data โยกย้ายโมเดลโดยอัตโนมัติ


96

ฉันได้อ่านเอกสารเกี่ยวกับการย้ายข้อมูลอัตโนมัติ / น้ำหนักเบาสำหรับโมเดลข้อมูลหลัก - แต่ฉันมีปัญหาในการใช้งาน

ตามที่ฉันเข้าใจแอปพลิเคชันควรสังเกตว่ารุ่นที่มีอยู่และรุ่นที่มีอยู่ในอุปกรณ์นั้นไม่เหมือนกัน หากคุณเพิ่มเฉพาะแอตทริบิวต์หรือความสัมพันธ์และการเปลี่ยนแปลงง่ายๆที่คล้ายกันโมเดลควรได้รับการอัปเกรดโดยอัตโนมัติ

ตัวชี้ใด ๆ - ฉันต้องตั้งค่าบางอย่างใน Xcode หรือไม่?

คำตอบ:


138

ตอนนี้ฉันพบแล้วว่ามันค่อนข้างง่าย - เมื่อคุณรู้ว่าจะต้องมองหาที่ไหน

ใน AppDelegate ของฉันฉันตั้งค่า NSPersistentStoreCoordinator - และคุณต้องเพิ่มตัวเลือกบางอย่างเพื่อบอกให้จัดการกับการโยกย้ายอัตโนมัติ:

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);
}

จากนั้นคุณต้องทำเคล็ดลับเล็กน้อยใน xCode:

  1. เลือกไฟล์ xcdatamodel ของคุณ
  2. เลือกเมนูออกแบบที่ด้านบนจากนั้นเลือกโมเดลข้อมูลจากนั้นเลือกเพิ่มรุ่นรุ่น
  3. จากนั้นไฟล์ xcdatamodel ของคุณจะถูกย้ายไปยังไดเร็กทอรีใหม่ที่มีชื่อเดียวกับไฟล์ xcdatamodel ของคุณ แต่มีนามสกุล xcdatamodeld - จะมีไฟล์ที่สองในไดเร็กทอรีนี้โดยมี 2 ในชื่อ เลือกไฟล์ใหม่แล้ว Design-> Data Model-> Set Current Version ( ใน Xcode 4 คุณทำสิ่งนี้ )
  4. หากคุณได้ทำการเปลี่ยนแปลงที่ทำให้โปรเจ็กต์ของคุณเข้ากันไม่ได้ให้นำการเปลี่ยนแปลงเหล่านี้ออกจากไฟล์ xcdatamodel ดั้งเดิม หากคุณยังไม่ได้ทำการเปลี่ยนแปลงให้แก้ไขไฟล์ 2.xcdatamodel (ไฟล์ที่คุณเพิ่งสร้างเป็นเวอร์ชันปัจจุบัน)
  5. ตอนนี้เมื่อคุณติดตั้งเวอร์ชันนี้ลงในอุปกรณ์ที่มีรุ่นเก่า - จะอัปเกรดรุ่นนั้นเป็นรุ่นใหม่โดยอัตโนมัติ

สิ่งนี้ดูดีและเรียบง่ายอย่างที่ฉันต้องการ แต่ฉันคิดว่าคุณต้องระมัดระวังในระหว่างการพัฒนาเมื่อคุณเปลี่ยนโมเดลมิฉะนั้นคุณจะต้องสร้างเวอร์ชันใหม่สำหรับการเปลี่ยนแปลงแต่ละครั้ง

ฉันคิดว่าสิ่งที่ฉันจะทำคือฉันจะเก็บไฟล์ที่เปลี่ยนแปลงทั้งหมดไว้จากนั้นเมื่อฉันพร้อมที่จะปรับใช้การอัปเดตของฉันฉันจะลบไฟล์ที่อยู่ระหว่างนั้นทั้งหมดและปรับใช้กับรุ่นที่เก่าที่สุดและล่าสุดเท่านั้น


อัพเดท (15/07/2554):

ขอบคุณ @ rockstarberlin ที่ชี้ให้เห็นว่ามีเอกสารอัปเดตที่ apple:

Xcode 4: การตั้งค่าเวอร์ชันปัจจุบันของ Managed Object Model

อัปเดต: 19/8/2556 ลิงค์ที่ดีกว่า:

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


ฉันขอแนะนำให้อ่าน Core Data Migration and Versioning Guide ซึ่งมีอยู่ใน Xcode doc viewer และใน developer.apple.com
Hunter

1
ฉันไม่พบคำตอบที่ระบุไว้ในนั้น - ต้องใช้เวลาสักพักในการค้นหาวิธีการทำเช่นนี้
Grouchal

NSInferMappingModelAutomaticallyOption ทำงานได้ดี แต่สำหรับการแมปแบบธรรมดาเท่านั้นเช่นการเปลี่ยนชื่อของแอตทริบิวต์ สำหรับสิ่งที่ซับซ้อนมากขึ้น (ความสัมพันธ์การลบหรือการเพิ่มเอนทิตี) คุณจะต้องเพิ่มโมเดลการแมป หาก Xcode บ่นว่า NSInferMappingModelAutomaticallyOption ไม่ได้ประกาศให้เพิ่ม #import <CoreData / CoreData.h> ลงในไฟล์ส่วนหัวของผู้แทนแอปของคุณ
Elise van Looij

ฉันเพิ่มเอนทิตีบางอย่างลงในโมเดลของฉันและได้รับข้อผิดพลาด "โมเดลที่ใช้เปิดร้านค้าไม่เข้ากันกับแบบจำลองที่ใช้สร้างร้านค้า" วิธีแก้ปัญหาของคุณได้รับการแก้ไขแล้ว! ขอบคุณมาก!
Karsten Silz

1
ดูคำตอบของ Santthosh ด้านล่างหากคุณได้รับข้อผิดพลาด "can't merge model with two different entities named" หลังจากทำตามคำแนะนำเหล่านี้
benvolioT

14

นี่เป็นประโยชน์อย่างเหลือเชื่อ เอกสารของ Apple - ตามปกติ - ไม่สมบูรณ์อย่างมาก ฉันขอแนะนำให้ทำการสร้างใหม่ทั้งหมดเนื่องจากฉันพบข้อผิดพลาด "ไม่สามารถผสานโมเดลกับสองเอนทิตีที่แตกต่างกัน xxx" เมื่อฉันเรียกใช้ครั้งแรกหลังจากทำการเปลี่ยนแปลง โครงสร้างที่สะอาดได้รับการแก้ไข


โครงสร้างที่สะอาดช่วยแก้ไขปัญหาของฉันด้วย
jrainbow

6

คำตอบของ Grouchal นั้นสมบูรณ์แบบ ... แต่หากคุณยังคงมี "ไม่สามารถผสานโมเดลกับสองเอนทิตีที่แตกต่างกัน xxx" แม้ว่าจะล้างบิวด์หลายครั้งแล้วก็ตาม ... คุณอาจมีปัญหาเกี่ยวกับวิธีการโหลดagedObjectModel .. . ลองดูอันนี้ ... ที่ช่วยแก้ไข ..

ปัญหาการย้ายข้อมูลหลัก


3

นอกจากนี้หากคุณสะดุดกับโพสต์นี้เช่นเดียวกับฉันหลังจากได้รับข้อผิดพลาด "โมเดลที่ใช้ในการเปิดร้านค้าไม่เข้ากันกับรุ่นที่ใช้สร้างร้านค้า" และคุณเพิ่งแก้ไขข้อบกพร่องโดยใช้โปรแกรมจำลองและต้องการแทนที่ ติดตั้งรุ่นเก่าแล้วคุณสามารถรีเซ็ตแอป Simulator หรือลบแอปของคุณออกจากโปรแกรมจำลองก็น่าจะใช้ได้เช่นกัน

ฉันไม่ได้ลองสิ่งนี้จนกว่าจะอ่านโพสต์ที่นี่ ณ จุดนั้นฉันก็รู้ว่าฉันได้ติดตั้งแอพในโปรแกรมจำลองแล้วเปลี่ยนโมเดลในภายหลังทำให้เกิดข้อผิดพลาดรันไทม์ดังกล่าวข้างต้น


1

หากต้องการติดตามคำตอบของ Santthosh ฉันคิดว่าฉันจะโพสต์ข้อมูลโค้ดที่นี่แทน คุณต้องสร้างagedObjectModelของคุณinitWithContentsOfURL:แทนmergedModelFromBundles:มิฉะนั้นคุณจะได้รับข้อผิดพลาด:

ไม่สามารถรวมโมเดลกับสองเอนทิตี XXX และ XXX ที่ต่างกัน

หากไฟล์ Model ของคุณมีชื่อว่า "Model" ต่อไปนี้เป็นวิธีสร้างagedObjectModel:

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

เครดิตสำหรับโพสต์บล็อกนี้


1

เมนูใน Xcode 4 เปลี่ยนไปเล็กน้อย นี่คือคำอธิบายวิธีการทำใน Xcode 4:

Xcode 4: การตั้งค่าเวอร์ชันปัจจุบันของ Managed Object Model


ลิงก์เสียแล้ว ลิงก์ไปยังเอกสารของ Apple ใช้เวลาประมาณสองเดือน :(
mxcl

1

ฉันมีปัญหานี้มาหลายปีแล้วและฉันได้ลองใช้คำตอบทั้งหมดนี้แล้ว แต่ก็ไม่มีประโยชน์ ในที่สุดวันนี้ฉันก็รู้ว่าฉันทำอะไรผิด ปัญหาง่ายมาก แต่ฉันมองข้ามมันไป เมื่อสร้างโมเดลข้อมูลเวอร์ชันใหม่กว่าหากคุณกำลังเพิ่มคอลัมน์ให้แน่ใจว่าได้ทำเครื่องหมายเป็นไม่บังคับ หากคุณไม่ทำการโอนย้ายแบบง่ายจะไม่ทำงานเนื่องจากค่าคอลัมน์ใหม่จะไม่ถูกกรอก

ทันทีที่ฉันแน่ใจว่าคอลัมน์ใหม่ของฉันมีการเลือก "ไม่บังคับ" ฉันก็ลองย้ายข้อมูลอีกครั้งและมันก็ใช้ได้


1

ฉันพบโพสต์นี้เนื่องจากปัญหาที่แตกต่างกัน แต่ข้อผิดพลาดคือ " การกำหนดค่าโมเดลที่ใช้ในการเปิดร้านค้าไม่เข้ากันกับที่ใช้ในการสร้างร้านค้า "

นี่คือปัญหาของฉันและวิธีแก้ปัญหา ในโมเดลของฉันฉันใช้การกำหนดค่าการกำหนดค่าฉันมีเอนทิตีบางส่วนถูกเก็บไว้ในไฟล์เดียวและอีกไฟล์หนึ่งในไฟล์ที่สอง (ฉันมีค่าเริ่มต้นบางอย่างที่อาจต้องดาวน์โหลดเป็นระยะ ๆ และมันจะเป็นความเจ็บปวดอย่างไม่น่าเชื่อที่จะรวมเข้าด้วยกันทั้งหมด) อย่างไรก็ตามฉันสร้างเอนทิตีใหม่ ดูเหมือนโปรแกรมจะทำงานได้ดี แต่เมื่อใดก็ตามที่ฉันปิดฉันได้รับข้อผิดพลาดข้างต้น

วิธีแก้ปัญหาคือดูที่การกำหนดค่าของฉันตระหนักว่าฉันมีเอนทิตีที่ไม่ได้อยู่ในการกำหนดค่าใด ๆ ในขณะนี้และเพิ่มเข้าไปในการกำหนดค่า วิ่งเหมือนฝัน

สิ่งนี้จะไม่สามารถแก้ไขปัญหาของ OP ได้ แต่บางทีคนที่ผิดหวังที่มาที่นี่ผ่านทาง google จะอยู่ในเรือที่ฉันอยู่ :)


0

iOS 4.0 ขึ้นไป

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

0

แก้ไขเล็กน้อยในคำแนะนำที่ยอดเยี่ยมของ @ Grouchal ด้านบนสำหรับ Xcode เวอร์ชัน 5:

เก่า: 2. เลือกเมนูออกแบบที่ด้านบนจากนั้นเลือกโมเดลข้อมูลจากนั้นเลือกเพิ่มรุ่นรุ่น

เวอร์ชัน 5+: 2. เลือกเมนูแก้ไขจากนั้นเพิ่มรุ่นรุ่น…พิมพ์ชื่อเวอร์ชันของคุณและอิงตามรุ่น (เลือกรุ่นเดิมของคุณจากรายการ)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.