Tôi đã đọc một số bài đăng ở đây về NSManagedObjectContext và các ứng dụng đa luồng. Tôi cũng đã đi qua ví dụ CoreDataBooks để hiểu cách các luồng riêng biệt yêu cầu NSManagedObjectContext của riêng họ và cách hoạt động lưu được hợp nhất với NSManagedObjectContext chính. Tôi tìm thấy ví dụ để được tốt, nhưng cũng quá cụ thể ứng dụng. Tôi đang cố gắng để khái quát hóa điều này, và tự hỏi liệu cách tiếp cận của tôi là âm thanh hay không.Cách tiếp cận chung cho NSManagedObjectContext trong ứng dụng đa luồng
Cách tiếp cận của tôi là có chức năng chung để tìm nạp NSManagedObjectContext cho chuỗi hiện tại. Hàm trả về NSManagedObjectContext cho luồng chính, nhưng sẽ tạo một mới (hoặc lấy nó từ một bộ nhớ đệm) nếu được gọi từ trong một luồng khác. Điều đó xảy ra như sau:
+(NSManagedObjectContext *)managedObjectContext {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;
NSThread *thread = [NSThread currentThread];
if ([thread isMainThread]) {
return moc;
}
// a key to cache the context for the given thread
NSString *threadKey = [NSString stringWithFormat:@"%p", thread];
// delegate.managedObjectContexts is a mutable dictionary in the app delegate
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;
if ([managedObjectContexts objectForKey:threadKey] == nil) {
// create a context for this thread
NSManagedObjectContext *threadContext = [[[NSManagedObjectContext alloc] init] autorelease];
[threadContext setPersistentStoreCoordinator:[moc persistentStoreCoordinator]];
// cache the context for this thread
[managedObjectContexts setObject:threadContext forKey:threadKey];
}
return [managedObjectContexts objectForKey:threadKey];
}
Thao tác lưu đơn giản nếu được gọi từ chuỗi chính. Lưu các hoạt động được gọi từ các luồng khác yêu cầu hợp nhất trong chuỗi chính. Cho rằng tôi có một generic commit
chức năng:
+(void)commit {
// get the moc for this thread
NSManagedObjectContext *moc = [self managedObjectContext];
NSThread *thread = [NSThread currentThread];
if ([thread isMainThread] == NO) {
// only observe notifications other than the main thread
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
NSError *error;
if (![moc save:&error]) {
// fail
}
if ([thread isMainThread] == NO) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:moc];
}
}
Trong contextDidSave:
chức năng chúng tôi thực hiện việc hợp nhất, nếu gọi bằng thông báo trong commit
.
+(void)contextDidSave:(NSNotification*)saveNotification {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = delegate.managedObjectContext;
[moc performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:saveNotification
waitUntilDone:YES];
}
Cuối cùng, chúng tôi làm sạch-up bộ nhớ cache của NSManagedObjectContext với điều này:
+(void)initialize {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(threadExit)
name:NSThreadWillExitNotification
object:nil];
}
+(void)threadExit {
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *threadKey = [NSString stringWithFormat:@"%p", [NSThread currentThread]];
NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;
[managedObjectContexts removeObjectForKey:threadKey];
}
này biên soạn và dường như làm việc, nhưng tôi biết luồng vấn đề có thể được khôn lanh do điều kiện chủng tộc. Có ai nhìn thấy một vấn đề với cách tiếp cận này?
Ngoài ra, tôi đang sử dụng điều này từ trong bối cảnh yêu cầu không đồng bộ (sử dụng ASIHTTPRequest), tìm nạp một số dữ liệu từ máy chủ và cập nhật và chèn cửa hàng trên iPhone. Dường như NSThreadWillExitNotification không kích hoạt sau khi yêu cầu hoàn thành, và cùng một luồng được sử dụng cho các yêu cầu tiếp theo. Điều này có nghĩa là cùng một NSManagedObjectContext được sử dụng cho các yêu cầu riêng biệt trên cùng một luồng. Đây co phải vân đê?
chris, tôi đang gặp phải sự cố đa luồng tương tự khi sử dụng một NSManagedObjectContext được tạo trong chuỗi chính cho tất cả các hoạt động trong Hàng đợi NSoperation. Các probkem đến khi mỗi thread cố gắng để lưu bối cảnh, các ứng dụng treo ngẫu nhiên ném một ngoại lệ từ dữ liệu cốt lõi. tôi đã suy nghĩ để khóa bối cảnh này trong khi sử dụng trong tất cả các hoạt động, để mỗi người trong số họ sẽ có quyền truy cập độc quyền của bối cảnh. Tôi đã đọc ur trên solution.sounds gud, couls u xin vui lòng dán cho tôi mã mới mà u đã sử dụng để sáp nhập bối cảnh và cũng xin vui lòng bình luận về cách sử dụng một khóa cho playin –