在插入新的子对象时,父子对象传递与多级的一对多关系。 IOS核心数据
Posted
技术标签:
【中文标题】在插入新的子对象时,父子对象传递与多级的一对多关系。 IOS核心数据【英文标题】:Parent to child object pass for one to many relationship with multilevel while inserting new child object . Ios Core data 【发布时间】:2015-05-18 12:56:00 【问题描述】:我在后台保存 coredata 时遇到问题。我正在实施以下模型:
MasterManagedObject(NSPrivateQueueConcurrencyType 类型) MainManagedObjectContext(类型为 NSMainQueueConcurrencyType & 是 MasterManagedObject 的子级) TemporaryManagedObjectContext(类型为 NSPrivateQueueConcurrencyType 并且是 MainManagedObjectContext 的子级)代码是:
- (NSManagedObjectContext *)masterManagedObjectContext
if (_masterManagedObjectContext)
return _masterManagedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self storeCoordinator];
if (coordinator != nil)
dime(@"Here in master context");
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
return _masterManagedObjectContext;
- (NSManagedObjectContext *)mainManagedObjectContext
if (_mainManagedObjectContext)
return _mainManagedObjectContext;
_mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainManagedObjectContext setParentContext:self.masterManagedObjectContext];
return _mainManagedObjectContext;
+ (NSManagedObjectContext *)temporaryWorkerContext
NSManagedObjectContext *tempMOContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
tempMOContext.parentContext = [[DDPersist manager] mainManagedObjectContext];
return tempMOContext;
保存上下文:
+ (void)saveTempContext:(NSManagedObjectContext *)context
NSError *error;
[context save:&error];
if (!error)
[[DDPersist manager] saveMainContext];
dime(@"Temp Context Saved");
else
dime(@"Temp Context Error = %@",error);
- (void)saveMainContext
[[[DDPersist manager] mainManagedObjectContext] performBlock:^
NSError *error = nil;
[[[DDPersist manager] mainManagedObjectContext] save:&error];
if(!error)
//Write to disk after saving on the main UI context
[[DDPersist manager] saveMasterContext];
dime(@"main Context Saved");
else
dime(@"Main Context Error = %@",error);
];
- (void)saveMasterContext
[self.masterManagedObjectContext performBlock:^
NSError *error = nil;
[self.masterManagedObjectContext save:&error];
if(error)
dime(@"Master Context Saved");
else
dime(@"Master Context Error %@", error);
if([NSThread isMainThread])
dime(@"Master Context Error NOT ON BACKGROUND CONTEXT! WILL AUTOMATICALLY PERSIST ON MAIN CTX!");
];
我正在使用上面在后台线程中创建新的 spaceChecklistItems 对象,如下所示: //space 是spaceCheckListItem 的父级,具有一对多的关系。
__block NSManagedObjectID *spaceObjectID = [space objectID];
//Background thread starts here
[DDPersist performTaskOnBackgroundCtxWithParentChildScheme:^(NSManagedObjectContext *bgCtx)
Space *localSpace = (Space*)[bgCtx objectWithID:spaceObjectID];
for(NSDictionary * spaceChecklistItemDict in spaceChecklistItems)
SpaceChecklistItem * spaceChecklistItem = [SpaceChecklistItemService importSpaceChecklistItem:spaceChecklistItemDict space:localSpace];
NSAssert(spaceChecklistItem, @"invalid SpaceChecklistItem at import!");
if(!spaceChecklistItem) continue;
[bgCtx obtainPermanentIDsForObjects:bgCtx.insertedObjects.allObjects error:nil];
[DDPersist saveTempContext:bgCtx];
];
后台上下文中使用的方法(importSpaceChecklistItem)如下:
+ (SpaceChecklistItem*)importSpaceChecklistItem:(NSDictionary*)itemDict space:(Space*)space
NSNumber *spaceChecklistItemId = [itemDict objectForKey:@"id"];
NSString * inspectionStatus ;
if ([itemDict objectForKey:@"inspectionStatus"])
inspectionStatus = [itemDict objectForKey:@"inspectionStatus"];
else
inspectionStatus = @"UNDECIDED";
NSString * notes = [itemDict objectForKey:@"notes"];
MOC * ctx = space.managedObjectContext;
SpaceChecklistItem * spaceChecklistItem = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([SpaceChecklistItem class])
inManagedObjectContext:ctx];
spaceChecklistItem.spaceChecklistItemId = spaceChecklistItemId;
spaceChecklistItem.space = space;// This is the relationship saving & not working.
spaceChecklistItem.inspectionStatus = inspectionStatus;
spaceChecklistItem.notes=notes;
spaceChecklistItem.sync = @NO;
return spaceChecklistItem;
主要问题是性能问题。我想从上面加速循环:for(NSDictionary * spaceChecklistItemDict in spaceChecklistItems)。并且想把所有的处理变成后台。这个 for 循环可能包含超过 50000 次迭代。这通常需要时间(大约 3 分钟)才能保存到 coredata 中。如果我使用单线程并在 main 的单线程子项(不是主上下文)中保持 for 循环,则数据正在保存。但是这种一对多的关系给我带来了问题,我为此苦苦挣扎了很长时间。
我阅读了许多 *** 问题和许多其他文章。但不能解决这个问题。任何帮助将不胜感激。
【问题讨论】:
您似乎没有在导入方法中创建任何spaceChecklistItem
。
@Mundi ,对不起,我在从实际代码复制到 *** 上的此处并删除额外代码时错过了该行。我现在更新了我的代码。
【参考方案1】:
您是否运行过 Instruments?
运行时间分析器并查看花费最多的时间。
将该跟踪发布到您的问题中,以便其他人也可以看到它。
【讨论】:
我可以补充,没问题。但是我目前在保存上下文时遇到了问题。仪器是完全不同的东西。如果我能以某种方式解决这个上下文保存问题,那么我认为它会解决所有问题。我在那里遇到了关系错误。 Instruments 是解决性能问题的首选工具。这是你第一个去看看为什么有些东西很慢的地方。这个保存问题,如果它没有产生错误,需要在 Instruments 中查看。否则你只是在浪费时间猜测和假设。这甚至可能不是核心数据问题,可能是线程问题,可能是数据问题。在时间分析器下运行它之前,你不会知道。说真的,这是第一步。以上是关于在插入新的子对象时,父子对象传递与多级的一对多关系。 IOS核心数据的主要内容,如果未能解决你的问题,请参考以下文章
如果同时保存的两个实体父子实体映射为一对多关系,则抛出 id not found 父类异常