日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CoreData 从入门到精通(四)并发操作

發布時間:2024/4/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CoreData 从入门到精通(四)并发操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

通常情況下,CoreData 的增刪改查操作都在主線程上執行,那么對數據庫的操作就會影響到 UI 操作,這在操作的數據量比較小的時候,執行的速度很快,我們也不會察覺到對 UI 的影響,但是當數據量特別大的時候,再把 CoreData 的操作放到主線程中就會影響到 UI 的流暢性。自然而然地我們就會想到使用后臺線程來處理大量的數據操作。

使用后臺 managedObjectContext

CoreData 里使用后臺更新數據最常用的方案是一個 persistentStoreCoordinator 持久化存儲協調器對應兩個 managedObjectContext 管理上下文,NSManagedObjectContext 在創建時,可以傳入 ConcurrencyType 來指定 context 的并發類型。指定 NSMainQueueConcurrencyType 就是我們平時創建的運行在主隊列的 context;指定成 NSPrivateQueueConcurrencyType 的話,context 就會運行在它所管理的一個私有隊列中;另外還有 NSConfinementConcurrencyType 是適用于舊設備的并發類型,現在已經被廢棄了,所以實際上只有兩種并發類型。
下面是創建 backgroundContext 的代碼:

NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; backgroundContext.persistentStoreCoordinator = self.persistentStoreCoordinator;

在最新的 iOS 10 中,CoreData 棧的創建被封裝在了 NSPersistentContainer 類中,用它來創建 backgroundContext 更加簡單:

NSManagedObjectContext *backgroundContext = ((AppDelegate *)[UIApplication sharedApplication].delegate).persistentContainer.newBackgroundContext;

另外,后臺 context 的操作得放在 performBlock 或 performBlockAndWait 方法里執行,performBlock 會異步的執行,不會阻塞當前的線程,而 performBlockAndWait 則會阻塞當前的線程直到方法返回才會繼續向下執行。下面是一段后臺插入數據的示例代碼:

[self.backgroundContext performBlock:^{for (NSUInteger i = 0; i < 100000; i++) {NSString *name = [NSString stringWithFormat:@"student-%d", arc4random_uniform(9999)]; int16_t age = arc4random_uniform(10) + 10; int16_t stuId = arc4random_uniform(9999); Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:self.backgroundContext]; student.studentName = name; student.studentAge = age; student.studentId = stuId; } NSError *error; [self.backgroundContext save:&error]; [self.logger dealWithError:error whenFail:@"failed to insert" whenSuccess:@"insert success"]; }];

后臺插入數據之后,還沒有完,因為數據是通過后臺的 context 寫入到本地的持久化數據庫的,所以這時候主隊列的 context 是不知道本地數據變化的,所以還需要通知到主隊列的 context:“數據庫的內容有變化啦,看看你有沒有需要合并的”。這個過程可以通過監聽一條通知來實現。這個通知就是 NSManagedObjectContextDidSaveNotification,在每次調用 NSManagedObjectContext 的 save:方法時都會自動發送,通知中的 userInfo 中包含了修改的數據,可以通過 NSInsertedObjectsKey、NSUpdatedObjectsKey、 NSDeletedObjectsKey 這三個 key 獲取到。


NSManagedObjectContextDidSaveNotification-w600

收到通知之后,只需要調用 [self.mainContext mergeChangesFromContextDidSaveNotification:note] 就可以將修改的數據合并到主線程的 context。

下面是示例代碼:

- (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveContextSave:) name:NSManagedObjectContextDidSaveNotification object:self.backgroundContext]; } - (void)doSometingInsertingInBackground { // backgroundContext .... } - (void)receiveContextSave:(NSNotification *)note { [self.context mergeChangesFromContextDidSaveNotification:note]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }

注意:通知的 userInfo 里保存的 managedObjects 不可以直接在另一個線程的 context 中直接使用!也就是 managedObject 不是跨線程的,如果想要在別的線程操作,必須通過 objectId 在另一個 context 里再重新獲得這個 object。

- (void)receiveContextSave:(NSNotification *)note {[self.context mergeChangesFromContextDidSaveNotification:note];NSSet<Student *> *managedObjects = note.userInfo[NSInsertedObjectsKey]; NSManagedObjectID *studentId = managedObjects.allObjects[0].objectID; [self.context performBlock:^{ // 這是錯的 // Student *wrongStudent = managedObjects.allObjects[0]; // 應該這么做 Student *student = [self.context objectWithID:studentId]; // modify student... }]; }

轉載于:https://www.cnblogs.com/Free-Thinker/p/7059726.html

總結

以上是生活随笔為你收集整理的CoreData 从入门到精通(四)并发操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。