Tôi có một dự án iOS với một cơ sở dữ liệu lớn, được tải sẵn và một cơ sở dữ liệu người dùng nhỏ (cả hai cửa hàng SQLite CoreData). Các câu hỏi trước đã đề xuất sử dụng các cấu hình để kiểm soát những Thực thể nào được sử dụng với cửa hàng nào. Tôi gặp khó khăn khi làm việc đó. Đây là những gì tôi đã cố gắng ...CoreData với nhiều cửa hàng: cấu hình tai họa
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) return _managedObjectModel;
// set up the model for the preloaded data
NSURL *itemURL = [[NSBundle mainBundle] URLForResource:@"FlagDB" withExtension:@"momd"];
NSManagedObjectModel *itemModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:itemURL];
// set up the model for the user data
NSURL *userDataURL = [[NSBundle mainBundle] URLForResource:@"UserData" withExtension:@"momd"];
NSManagedObjectModel *userDataModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:userDataURL];
// merge the models
_managedObjectModel = [NSManagedObjectModel modelByMergingModels:[NSArray arrayWithObjects:itemModel, userDataModel, nil]];
// define configurations based on what was in each model
WRONG [_managedObjectModel setEntities:itemModel.entities forConfiguration:@"ItemData"];
WRONG [_managedObjectModel setEntities:userDataModel.entities forConfiguration:@"UserData"];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator;
// preloaded data is inside the bundle
NSURL *itemURL = [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"FlagDB.sqlite"];
// user data is in the application directory
NSURL *userDataURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UserData.sqlite"];
NSManagedObjectModel *mom = self.managedObjectModel;
NSError *error = nil;
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:nil error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
...
Hủy bỏ này với "Mô hình được sử dụng để mở cửa hàng không tương thích với cửa hàng được sử dụng để tạo cửa hàng". Kiểm tra các hash trong mô hình đối với các hash trong kho lưu trữ rằng chúng giống hệt nhau đối với các thực thể có trong cấu hình ItemData.
Nếu tôi cố gắng làm một sự chuyển đổi trọng lượng nhẹ, như vậy:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:options error:&error])
Nó không thành công với 'NSInvalidArgumentException', lý do: ' '' mẫu không chứa cấu hình' ItemData Tôi cho rằng đó là vì một mô hình mới đang được tạo ra bởi quá trình di chuyển nhẹ và nó không chứa cấu hình của tôi.
Dựa trên một số đề xuất trong các chủ đề khác, tôi đã thử thực hiện di chuyển nhẹ mà không cần cấu hình và sau đó tạo điều phối viên mới bằng cấu hình. Loại công việc này, nhưng nó thêm các bảng vào tệp .sqlite được tải sẵn của tôi tương ứng với các thực thể dữ liệu người dùng (không thuộc về đó) và tạo cả các bảng dữ liệu được tải sẵn và các bảng dữ liệu người dùng trong kho dữ liệu người dùng mới được tạo ra. . Kết quả cuối cùng là tìm nạp thất bại, dường như bởi vì họ đang tìm kiếm trong cửa hàng sai.
NSDictionary *migrationOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
// make a temp persistent store coordinator to handle the migration
NSPersistentStoreCoordinator *tempPsc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
// migrate the stores
if (![tempPsc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:itemURL options:migrationOptions error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
if (![tempPsc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:userDataURL options:migrationOptions error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// make a permanent store coordinator
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSDictionary *readOnlyOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSReadOnlyPersistentStoreOption, nil];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"ItemData" URL:itemURL options:readOnlyOptions error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
/*if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:@"UserData" URL:userDataURL options:nil error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}*/
Và sau đó ...
OSAppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = delegate.managedObjectContext;
// sanity check
for (NSPersistentStore *store in context.persistentStoreCoordinator.persistentStores) {
NSLog(@"store %@ -> %@", store.configurationName, store.URL);
NSMutableArray *entityNames = [[NSMutableArray alloc] init];
for (NSEntityDescription *entity in [context.persistentStoreCoordinator.managedObjectModel entitiesForConfiguration:store.configurationName]) {
[entityNames addObject:entity.name];
}
NSLog(@"entities: %@", entityNames);
}
NSFetchRequest *categoryFetchRequest = [[NSFetchRequest alloc] init];
categoryFetchRequest.entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context];
categoryFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", categoryName];
NSError *error = nil;
Category *category = [[delegate.managedObjectContext executeFetchRequest:categoryFetchRequest error:&error] lastObject];
này hoạt động tốt, trở về đối tượng loại tên một cách thích hợp, cho đến khi tôi bỏ ghi chú việc bổ sung các cửa hàng thứ hai. Nếu tôi làm điều đó, kết quả tìm nạp sẽ trở lại trống. Các thông điệp NSLog chẩn đoán in chính xác những gì tôi mong đợi. Mỗi cửa hàng được liên kết với cấu hình chính xác và mỗi cấu hình có các thực thể thích hợp.
Có ai có thể chỉ cho tôi mã nguồn để thiết lập nhiều cửa hàng đang hoạt động hay không hay biết tôi đang làm gì sai? Cảm ơn trước!
SOLVED: Điểm mấu chốt của vấn đề là hai dòng đánh dấu sai trong các mã đầu tiên trong danh sách. Tôi đã cố tạo cấu hình theo lập trình, nhưng điều đó dường như không đủ. Nếu bạn truy vấn ManagedObjectModel cho các cấu hình sau khi thực hiện việc này, bạn làm thực sự thấy các cấu hình trong danh sách và các thực thể đúng được liên kết với các cấu hình đó. Tuy nhiên, có vẻ như một cái gì đó khác cần phải được thực hiện để làm cho PersistentStoreCoordinator có thể sử dụng đúng cách. Tạo cấu hình trong Xcode làm cho chúng hoạt động.
THEO D 01I: Có thêm một dấu phụ. Các giải pháp chạy một di chuyển riêng biệt vượt qua trước khi thiết lập cuối cùng Persistent Store Điều phối viên hoạt động tuyệt vời ... trong giả lập. Trên một thiết bị thực tế, các điều khoản sẽ nghiêm ngặt hơn. Nếu bạn cố gắng thực hiện di chuyển đó, nó không thành công vì cửa hàng trong gói Ứng dụng là chỉ đọc. Việc di chuyển có vẻ là cần thiết trừ khi bạn hợp nhất các mô hình của mình. Nếu bạn chỉ có một mô hình và cửa hàng trong gói Ứng dụng tương thích với nó, việc di chuyển là không cần thiết và truy cập bằng cách sử dụng cấu hình được xác định trong Xcode hoạt động.
Tùy chọn khác có thể là di chuyển dữ liệu vào thư mục Tài liệu trước khi thử di chuyển. Tôi chưa xác minh rằng cách tiếp cận đó hoạt động.
Đảm bảo bạn đang thực hiện di chuyển trên thư mục tài liệu người dùng của hộp cát ứng dụng - đó là đọc/ghi - chứ không phải trong chính gói ứng dụng. – Sunny
Tôi không muốn di chuyển dữ liệu vào thư mục Tài liệu vì tôi không muốn dữ liệu (tĩnh) đó được sao lưu và được tính vào hạn ngạch iCloud của người dùng. Nhưng có vẻ như trong iOS 5.0.1 có một cách để chỉ định các tệp không được sao lưu: http://developer.apple.com/library/ios/#qa/qa1719/_index.html – Aneel
Vâng, bạn đã truyền cảm hứng cho tôi và sau khi dành một vài giờ để giải quyết vấn đề của tôi, tôi đã viết một bài báo đầy đủ về điều này [ở đây] (http://blog.atwam.com/blog/2012/05/11/multiple-persistent-stores-and-seed-data -with-core-data /). Tôi nghĩ rằng nó có thể giúp một số người khác trong tương lai. – Wam