gpt4 book ai didi

ios - 在不同的线程中获取和使用 NSManagedObject

转载 作者:行者123 更新时间:2023-11-29 00:40:29 24 4
gpt4 key购买 nike

我在构建代码时遇到问题。我有 view 创建并依赖于 model 类。模型类负责所有的计算和逻辑。这意味着它有很多东西要计算,并从核心数据中获取对象。

enter image description here

关于 enter link description here ,在一个线程中获取的每个NSManagedObject,都需要在同一个线程中使用。

我的问题是创建对象需要在不同的线程中获取,因为构建模型需要一些时间,但在此之后,我需要从 View 的主线程中获取对象及其属性(例如在 cellForIndex. ..)

我知道,我不是唯一拥有这种设计的人。其他人如何解决这个问题?


编辑:

用代码具体化。

假设我们有 UIView 对象 MyUIView 和模型对象 Model

MyUIView

 @interface MyUIView ()

@property(nonatomic) Model * model;

@end

@implementation MyUIView

- (void) createModel
{
// privateManagerContext is context manager created with
// NSPrivateQueueConcurrencyType, connected to persistent store
// and sync with "main thread" manager context with
// NSManagedObjectContextDidSaveNotification and NSManagedObjectContextDidSaveNotification

[self.model createWithManagadContext:privateManagerContext];
}

// ASSUME THAT THIS CODE IS CALLED AFTER
- (void) getNumberOfSomeProperties
{
int number = [self.model getNumberOfProperties];
}

- (void) getProperties
{
NSArray *array = [self.model properties]
}

// OR WE HAVE TO TRIGGERED SOME LONG CALCULATION

- (void) triggerLongCalculation
{
[self.model longCalculation];
}

- (void) afterNotifyModelIsCompletedCalculating
{
[self doSomeWork];
[self getProperties];
....
}
@end

Model

 @interface Model ()

@property(nonatomic) NSArray * cashedProperties;

@end

@implementation MyUIView

- (void) createWithManagadContext:(NSManagedObjectContext *) privateManagerContext
{
dispatch_async(self.model_queue, ^(void){

// Here we fetch objects and do some calculations
[self populateModel];

/// Model is complete
[Notifications notifyModelIsCompletedCreating:self];
});
}


- (void) longCalculation
{
dispatch_async(self.model_queue, ^(void){
// NO CORE DATA FETCH INVOLVED
[Notifications notifyModelIsCompletedCalculating:self];
});
}

- (int) getNumberOfProperties
{
return self.cashedProperties.count;
}

- (NSArray) properties
{
NSMutableArray * a = [[NSMutableArray alloc]init];
for (Property * p in self.cashedProperties) {
[a addObject:p.name];
}

return a;
}

@end

那么在这个假设的类中,您将如何处理所有 NSManagedObject 和 NSManagedObjectContext ?

编辑 2:


我使用的模式是在 appdelegate 中创建两个托管对象上下文,一个是私有(private)的,一个是主要的,并在它们之间创建同步。

- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}

- (NSManagedObjectContext * ) privateQueueContext
{
if (_privateQueueContext != nil) {
return _privateQueueContext;
}

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateQueueContext setPersistentStoreCoordinator:coordinator];
}
return _privateQueueContext;
}


- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSavePrivateQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self privateQueueContext]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSaveMainQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self managedObjectContext]];
}
return self;
}

#pragma mark - Notifications

- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.managedObjectContext performBlock:^{

NSArray* objects = [notification.userInfo valueForKey:NSUpdatedObjectsKey];
for (NSManagedObject* obj in objects) {
NSManagedObject* mainThreadObject = [self.managedObjectContext objectWithID:obj.objectID];
[mainThreadObject willAccessValueForKey:nil];
}

[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}

- (void)contextDidSaveMainQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.privateQueueContext performBlock:^{

NSArray* objects = [notification.userInfo valueForKey:NSUpdatedObjectsKey];
for (NSManagedObject* obj in objects) {
NSManagedObject* mainThreadObject = [self.privateQueueContext objectWithID:obj.objectID];
[mainThreadObject willAccessValueForKey:nil];
}

[self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}

最佳答案

您可以使用两个不同的 NSManagedObjectContext 和父/子配置。主队列中用于 UI 的父级,专用队列中用于繁重工作的子级。一旦子上下文完成执行他将保存的繁重工作,其更改就会传播到主上下文。如果您在 View Controller 中使用 TableView ,则可以使用在主上下文上观察的 NSFetchedResultsController 。一旦主上下文接收并合并来自子上下文的更改,只要实现其委托(delegate)方法,NSFetchedResultsController 就会相应地更新 UI。

如果您不使用 NSFRC,您可以注册通知的主上下文“name:NSManagedObjectContextObjectsDidChangeNotification”或“name:NSManagedObjectContextObjectsDidSaveNotification”,并查看已添加/删除/更新了哪些对象,并相应地更新 UI。

如果您使用父/子线程限制(Apple 在过去几年中已废弃),您可能希望在线程之间传递 objectID 并在需要的上下文中获取对象,因为 NSManagedObjects 不是线程安全的。

代码:

首先,我不会在 View 中引用您的模型。 View 应该只是愚蠢的,并公开要填充的导出或方法。我将有一个 ViewController 与模型和 View 进行通信。

假设每次您需要执行繁重的工作时,您都有一个 util 方法来创建工作上下文(作为主队列中父级的子上下文)。

func newWorkerContext() -> NSManagedObjectContext {
let workerContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
workerContext.parentContext = self.mainContext
return workerContext
}

在你的模型中你会有

//Lets say you have a reference to your workerContext
func longCalculation() {
workerContext.performBlock({ () -> Void in
//Heavy process of information
//Once finished you save the worker context and changes are propagated to the parent context
})

}

在你的 ViewController 中你会拥有

class MyViewController: UIViewController {

func viewDidLoad() {
super.viewDidLoad()

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(handleDataModelChange(_:)), name: NSManagedObjectContextObjectsDidChangeNotification, object: REFERENCE_TO_MAIN_CONTEXT)
}

func deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: NSManagedObjectContextObjectsDidChangeNotification, object: REFERENCE_TO_MAIN_CONTEXT)
}

func handleDataModelChange(notification: NSNotification) {

//Check changes are relevant for the UI you are updating and if so update.
if let changedObjects = changes[NSUpdatedObjectsKey] as? NSSet {
}
if let insertedObjects = changes[NSInsertedObjectsKey] as? NSSet {
}
if let deletedObjects = changes[NSDeletedObjectsKey] as? NSSet {
}
}
}

请记住,要将更改保存在持久性存储中,您必须保存在主上下文中。这是一个简单的示例,但我希望它能让您了解现在要做什么。

关于ios - 在不同的线程中获取和使用 NSManagedObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39632828/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com