【发布时间】:2017-01-30 15:57:11
【问题描述】:
我在构建代码时遇到问题。
我有 view 创建并依赖于 model 类。模型类负责所有的计算和逻辑。这意味着它有很多东西要计算,并从核心数据中获取对象。
关于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
型号
@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 中创建两个托管对象上下文,一个是私有的,一个是主的,并在它们之间创建同步。
- (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];
}];
}
}
【问题讨论】:
-
您可以在主线程中加载对象,也可以创建对象的非托管版本并在计算完成后将其传递给主线程。
标签: ios objective-c core-data objective-c-blocks nsmanagedobject