Tôi đã tìm ra những gì Apple gợi ý trong tài liệu của họ . Nó thực sự rất dễ dàng nhưng một chặng đường dài trước khi nó trở nên rõ ràng. Tôi sẽ minh họa lời giải thích bằng một ví dụ. Tình huống ban đầu là:
Phiên bản mô hình dữ liệu 1
Đây là mô hình bạn nhận được khi tạo dự án với mẫu "ứng dụng điều hướng có lưu trữ dữ liệu cốt lõi". Tôi đã biên dịch nó và thực hiện một số thao tác khó với sự trợ giúp của vòng lặp for để tạo khoảng 2k mục nhập với một số giá trị khác nhau. Chúng ta có 2.000 sự kiện với giá trị NSDate.
Bây giờ chúng tôi thêm phiên bản thứ hai của mô hình dữ liệu, trông giống như sau:
Phiên bản mô hình dữ liệu 2
Sự khác biệt là: Thực thể Sự kiện đã biến mất và chúng tôi có hai thực thể mới. Một cái lưu trữ một dấu thời gian dưới dạng một double
và cái thứ hai sẽ lưu trữ một ngày tháng dưới dạng NSString
.
Mục tiêu là chuyển tất cả Sự kiện phiên bản 1 sang hai thực thể mới và chuyển đổi các giá trị trong quá trình di chuyển. Điều này dẫn đến hai lần các giá trị, mỗi giá trị là một kiểu khác nhau trong một thực thể riêng biệt.
Để di chuyển, chúng tôi chọn di chuyển bằng tay và điều này chúng tôi thực hiện với các mô hình bản đồ. Đây cũng là phần đầu tiên của câu trả lời cho câu hỏi của bạn. Chúng tôi sẽ thực hiện di chuyển trong hai bước, vì mất nhiều thời gian để di chuyển 2k mục nhập và chúng tôi muốn giữ cho bộ nhớ thấp.
Bạn thậm chí có thể tiếp tục và chia nhỏ các mô hình ánh xạ này để chỉ di chuyển các phạm vi thực thể. Giả sử chúng tôi có một triệu bản ghi, điều này có thể làm hỏng toàn bộ quá trình. Có thể thu hẹp các thực thể được tải xuống bằng một vị từ Bộ lọc .
Quay lại hai mô hình ánh xạ của chúng tôi.
Chúng tôi tạo mô hình ánh xạ đầu tiên như sau:
1. Tệp mới -> Tài nguyên -> Mô hình ánh xạ
2. Chọn tên, tôi đã chọn StepOne
3. Đặt mô hình dữ liệu nguồn và đích
Mô hình lập bản đồ Bước một
Di chuyển nhiều lần không cần chính sách di chuyển thực thể tùy chỉnh, tuy nhiên, chúng tôi sẽ thực hiện điều đó để có thêm một chút chi tiết cho ví dụ này. Vì vậy, chúng tôi thêm một chính sách tùy chỉnh vào thực thể. Đây luôn là một lớp con của NSEntityMigrationPolicy
.
Lớp chính sách này thực hiện một số phương thức để làm cho quá trình di chuyển của chúng ta diễn ra. Tuy nhiên nó đơn giản trong trường hợp này vì vậy chúng tôi sẽ phải thực hiện phương pháp duy nhất: createDestinationInstancesForSourceInstance:entityMapping:manager:error:
.
Việc triển khai sẽ như thế này:
StepOneEntityMigrationPolicy.m
#import "StepOneEntityMigrationPolicy.h"
@implementation StepOneEntityMigrationPolicy
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
entityMapping:(NSEntityMapping *)mapping
manager:(NSMigrationManager *)manager
error:(NSError **)error
{
NSManagedObject *newObject =
[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
inManagedObjectContext:[manager destinationContext]];
NSDate *date = [sInstance valueForKey:@"timeStamp"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"];
[dateFormatter release];
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
return YES;
}
Bước cuối cùng: chính quá trình di chuyển
Tôi sẽ bỏ qua phần thiết lập mô hình ánh xạ thứ hai gần như giống hệt nhau, chỉ là timeIntervalSince1970 được sử dụng để chuyển đổi NSDate thành double.
Cuối cùng, chúng ta cần kích hoạt quá trình di chuyển. Bây giờ tôi sẽ bỏ qua đoạn mã soạn sẵn. Nếu bạn cần, tôi sẽ đăng ở đây. Nó có thể được tìm thấy tại Customizing the Migration Process, nó chỉ là sự hợp nhất của hai ví dụ mã đầu tiên. Phần thứ ba và phần cuối cùng sẽ được sửa đổi như sau: Thay vì sử dụng phương thức lớp của NSMappingModel
lớp, mappingModelFromBundles:forSourceModel:destinationModel:
chúng ta sẽ sử dụng initWithContentsOfURL:
phương thức bởi vì phương thức lớp sẽ chỉ trả về một, có thể là mô hình ánh xạ đầu tiên, được tìm thấy trong gói.
Bây giờ chúng ta đã có hai mô hình ánh xạ có thể được sử dụng trong mỗi lần vượt qua vòng lặp và gửi phương thức di chuyển đến trình quản lý di chuyển. Đó là nó.
NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil];
NSDictionary *sourceStoreOptions = nil;
NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"];
NSString *destinationStoreType = NSSQLiteStoreType;
NSDictionary *destinationStoreOptions = nil;
for (NSString *mappingModelName in mappingModelNames) {
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"];
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];
BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
type:sourceStoreType
options:sourceStoreOptions
withMappingModel:mappingModel
toDestinationURL:destinationStoreURL
destinationType:destinationStoreType
destinationOptions:destinationStoreOptions
error:&error2];
[mappingModel release];
}
Ghi chú
Một mô hình ánh xạ kết thúc trong cdm
gói.
Cửa hàng đích phải được cung cấp và không được là cửa hàng nguồn. Bạn có thể sau khi di chuyển thành công xóa cái cũ và đổi tên cái mới.
Tôi đã thực hiện một số thay đổi đối với mô hình dữ liệu sau khi tạo các mô hình ánh xạ, điều này dẫn đến một số lỗi tương thích mà tôi chỉ có thể giải quyết bằng cách tạo lại các mô hình ánh xạ.