Đây là một lỗi được biết (bối cảnh lồng nhau không nhận ID vĩnh viễn khi các đối tượng mới được lưu) có thể, và phải được cố định trong một bản phát hành sắp tới ...
Bạn sẽ có thể yêu cầu ID vĩnh viễn mặc dù , nhưng bạn chỉ nên yêu cầu chúng trên các đối tượng đã được chèn vào.
[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:0];
Bạn phải làm điều này trước khi lưu MOC, vì nếu bạn lưu mà không có ID cố định, ID tạm thời sẽ được truyền sang ngữ cảnh gốc. Ví dụ, trong trường hợp của bạn, nơi bạn lưu vào mainMoc, sau đó lấy IDS, backgroundMOC vẫn có các ID tạm thời, do đó lưu trong tương lai từ nó sẽ tạo ra dữ liệu trùng lặp.
Lưu ý rằng việc lấy ID cố định sẽ chuyển sang cơ sở dữ liệu, nhưng nếu bạn đang thực hiện nó trong MOC con của MOC chính, bạn không nên chặn luồng chính trong khi điều này xảy ra.
Vì vậy, trong bạn tiết kiệm từ MOC mức thấp nhất của bạn, bạn có hiệu quả cần phải có một cái gì đó như thế này (với xử lý lỗi thích hợp, tất nhiên) ...
[backgroundMoc performBlock:^{
[backgroundMoc obtainPermanentIDsForObjects:backgroundMoc.insertedObjects.allObjects error:0];
[backgroundMoc save:0];
[mainMoc performBlock:^{
[mainMoc save:0];
[masterMoc performBlock:^{
[masterMoc save:0];
}];
}];
}];
Có một số trò chơi khác mà bạn có thể chơi, nếu bạn muốn.
Cung cấp một chủng loại trên NSManagedObject tương tự như sau ...
@implementation NSManagedObject (initWithPermanentID)
- (id)initWithEntity:(NSEntityDescription *)entity insertWithPermanentIDIntoManagedObjectContext:(NSManagedObjectContext *)context {
if (self = [self initWithEntity:entity insertIntoManagedObjectContext:context]) {
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:@[self] error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
}
return self;
}
+ (NSArray*)createMultipleObjects:(NSUInteger)count withEntity:(NSEntityDescription *)entity inManagedObjectContext:(NSManagedObjectContext *)context {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
for (NSUInteger i = 0; i < count; ++i) {
[array addObject:[[self alloc] initWithEntity:entity insertIntoManagedObjectContext:context]];
}
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:array error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
return array;
}
@end
Bây giờ, trong cái đầu tiên, bạn đang trả tiền để đi vào cơ sở dữ liệu và tạo ra một ID cho từng đối tượng được tạo ra, nhưng nó không phải là nhiều, và nó đang xảy ra trong một chủ đề nền, và mỗi lần nhúng ngắn ...
Ồ, nó không phải là tốt nhất, nhưng nó đã cung cấp hữu ích. Ngoài ra, thứ hai tạo nhiều đối tượng giống nhau và lấy cùng lúc ID của chúng.
Bạn cũng có thể sử dụng MOC được kết nối trực tiếp với PSC và xem các sự kiện DidChange, nhưng cũng giống như cách cũ. Thật không may, bạn không thể có một MOC riêng biệt chỉ cần thực hiện các yêu cầu persistentID và vượt qua ObjectID, mặc dù bạn có thể có một đối tượng nguyên mẫu làm MOC riêng biệt trong DB và cung cấp cho bạn ObjectID của chúng.
Nhà máy sản xuất mẫu thử nghiệm là một mẫu khá phổ biến và nếu bạn sử dụng tuyến đường đó, bạn sẽ dễ dàng thực hiện thay đổi nhỏ khi sửa lỗi cuối cùng tại đây.
EDIT
Để đối phó với Sven ...
Nếu bạn đang tạo mới, đồ thị phức tạp, sau đó bạn cần để có được một ID vĩnh viễn ngay lập tức sau khi tạo. Để giảm số lần truy cập vào cửa hàng, bạn nên tạo tất cả các lần truy cập, sau đó lấy các ID cùng một lúc, sau đó bắt đầu gắn chúng lên.
Thành thật mà nói, tất cả điều này là để giải quyết các lỗi hiện đang tồn tại, rất đáng để làm việc với các bản cập nhật có kích thước vừa và nhỏ. Mã của bạn sẽ giống nhau (không có được) khi các lỗi được sửa. Vì vậy, tôi đề nghị phương pháp này cho nhập khẩu nhỏ hơn.
Nếu bạn đang thực hiện cập nhật quy mô lớn, tôi khuyên bạn nên sử dụng phương pháp "cũ". Tạo một MOC mới được kết nối trực tiếp với PSC. Thực hiện tất cả các thay đổi của bạn ở đó và có ngữ cảnh "sống" của bạn chỉ cần hợp nhất từ các thông báo DidSave đó.
Cuối cùng, về tác động cơ sở dữ liệu của ID cố định. Có thể loại bỏ MOC. Đĩa được nhấn và siêu dữ liệu được thay đổi, nhưng các đối tượng không được lưu giữ.
Thành thật mà nói, tôi đã không làm một thử nghiệm lớn để xem liệu có bất kỳ không gian trống nào, do đó, bạn có thể muốn làm điều đó và quay lại với tôi.
Nhìn vào kích thước tệp cơ sở dữ liệu thực trên đĩa, sau đó tạo 10000 đối tượng, sau đó nhận ID liên tục, giải phóng MOC và xem lại kích thước.
Nếu có tác động, bạn có thể thử xóa các đối tượng hoặc chạy chân không trên cơ sở dữ liệu sau khi cập nhật lớn để xem có hoạt động hay không.
Nếu bạn định tạo nhiều đối tượng mà bạn có thể vứt bỏ, thì không cần phải nhấn vào cơ sở dữ liệu. Bạn có thể chỉ cần đính kèm trực tiếp vào PSC và sử dụng các thông báo trung thành cũ.
@Sven tại sao bạn đặt tiền thưởng cho điều này? Bạn có một vấn đề tương tự? – Snowman
Đúng, đó là gần như chính xác cùng một vấn đề tôi đang phải đối mặt. – Sven
"Giải pháp" của tôi là loại bỏ thiết lập chính/chính/con và chỉ sử dụng chính/con, để lưu trữ liên tục được liên kết với hàng đợi chính thay vì hàng đợi nền. – Snowman