Tại sao phải migrate data?

Tôi viết một ứng dụng cho nhân viên điều tra thị trường cửa một công ty marketing có thể cầm iPhone đi khắp nơi nhập dữ liệu. Do kết nối Internet không đảm bảo do đó, tôi sử dụng CoreData để lưu trữ dữ liệu điều tra vào ứng dụng, khi có kết nối Internet, dữ liệu sẽ được đẩy lên web server.

Mọi việc diễn ra tốt đẹp. Ứng dụng được cài đặt trên thiết bị của nhân viên điều tra thị trường bằng In-house Enterprise Distribution.
Khoảng hai tháng sau, khách hàng lại yêu cầu tôi bổ xung thêm một nhiều trường vào ứng dụng điều tra nhưng không được phép xoá bỏ dữ liệu cũ đã nhập.

Trong trường hợp nâng cấp ứng dụng và thay đổi cấu trúc model của CoreData như thế này, bắt buộc tôi phải sử cơ chế Data Migration cho phép di cư (migrate) dữ liệu cũ vào model mới của CoreData.

Khi nào có thể migrate data?

Có vài cấp độ migrate data. Cấp độ dễ nhất là “Lightweight migration”. Lightweight migration chỉ thực hiện thành công giới hạn đối với những thay đổi trong model của CoreData như sau:

  • Simple addition of a new attribute: thêm mới một attribute (thêm mới một cột)
  • Removal of an attribute: bỏ attribute ra khỏi một entity (tương đương bỏ cột)
  • A non-optional attribute becoming optional: chuyển thuộc tính bắt buộc thành không bắt buộc
  • An optional attribute becoming non-optional, and defining a default value
  • Renaming an entity or property: đổi tên entity hoặc property

Đối với trường hợp thay đổi phức tạp khiến cho Lightweight migration không thành công, ứng dụng sẽ báo lỗi “Model of CoreData is not found”.

Các bước để lightweight migrate data

Học lập trình iOS trực tuyến cơ bản
Add Model Version
Tạo một version mới kết thừa từ version cũ
Tạo một version mới kết thừa từ version cũ

Chọn một phiên bản cụ thể của CoreData model

Chọn phiên bản cụ thể của Model
Chọn phiên bản cụ thể của Model

Chỉnh sửa lại đoạn code cấu hình CoreData trong AppDelegate.m: chúng cần sửa trong hàm getter của thuộc tính persistentStoreCoordinator để bổ xung lựa chọn kiểu NSDictionary  @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

Với lựa chọn này: CoreData sẽ chủ động migrade dữ liệu cũ vào model mới và ánh xạ những attribute bị đổi tên.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    ...
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                         options:@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
                                                           error:&error]) {
    ...
}    
    
    return _persistentStoreCoordinator;
}

Thử nghiệm

Các bạn có thể thực hành bằng tạo ra một CoreData model gọi là version gốc, sau đó thêm dữ liệu. Tạo một phiên bản mới của model, chọn chế độ Lightweight migration rồi query dữ liệu cũ, đồng thời thêm dữ liệu mới. Nếu ứng dụng sau khi chỉnh sửa CoreData model mà không bị crash có nghĩa quá trình migration thành công.

Ví dụ mẫu

Ví dụ dự án mẫu demo tính năng Lightweight migration trong CoreData