如何在其他 NSManagedObjectContext 中插入 NSManagedObject?
Posted
技术标签:
【中文标题】如何在其他 NSManagedObjectContext 中插入 NSManagedObject?【英文标题】:How to insert NSManagedObject in other NSManagedObjectContext? 【发布时间】:2013-08-07 10:35:58 【问题描述】:我正在从服务器获取数据并将它们转换为 NSManagedObject 对象数组。 该数组用于显示表格。
如何在持久存储中插入第一个元素数组peoples?
- (void)viewDidLoad
[self loadData];
[self insertFirstPeople];
- (NSManagedObjectContext *)managedObjectContext
if(!_managedObjectContext) _managedObjectContext = [NSManagedObjectContext MR_context];
return _managedObjectContext;
- (void)loadData
...
Network Request
...
peoples = [NSMutableArray array];
for (NSDictionary *item in items)
People *people = [Podcast MR_createInContext:self.managedObjectContext];
people.name = [item valueForKeyPath:@"im:name.label"];
[peoples addObject:people];
-(void)insertFirstPeople
People *people = peoples[0];
NSManagedObjectContext *moc = [NSManagedObjectContext MR_defaultContext];
[moc insertObject:people]
[moc MR_saveToPersistentStoreAndWait];
错误:
An NSManagedObject may only be in (or observed by) a single NSManagedObjectContext.
【问题讨论】:
您是否打算使用两个不同的托管对象上下文?您真的只想要在默认上下文中插入的 first People 对象吗?在后台上下文中创建的其他对象呢? 是的。我想使用两个上下文。第一个只建表,第二个保存持久化存储 好的,但是你想将 all People 对象保存到持久存储中还是只保存 first 对象? 只有第一个对象 这可能很难/不可能。您可以将对象从一个上下文转移到另一个上下文(例如使用[people MR_inContext:[NSManagedObjectContext MR_defaultContext]]
),但这仅在对象已保存时才有效。保存背景上下文将保存 all 对象。更准确地说,由于背景上下文是默认上下文的子上下文,保存背景上下文意味着所有插入的对象都插入到默认上下文中。
【参考方案1】:
我自己已经找到了解决问题的方法。
-(void)insertFirstPeople
People *people = peoples[0];
CoreDataHelper *helper = [[CoreDataHelper alloc] init];
NSManagerObjectContext *context = [NSManagedObjectContext MR_defaultContext];
[helper saveObject:people toContext:context];
[context MR_saveOnlySelfAndWait];
CoreDataHelper.h
#import <Foundation/Foundation.h>
@interface CoreDataHelper : NSObject
NSMutableDictionary* _lookup;
@property(nonatomic, retain) NSMutableDictionary *lookup;
-(void)saveFrom:(NSManagedObjectContext *)current to:(NSManagedObjectContext *)parent;
- (NSManagedObject *)saveObject:(NSManagedObject *)object toContext:(NSManagedObjectContext *)moc;
- (NSManagedObject*)copyObject:(NSManagedObject*)object
toContext:(NSManagedObjectContext*)moc
parent:(NSString*)parentEntity;
@end
CoreDataHelper.m
#import "CoreDataHelper.h"
@implementation CoreDataHelper
@synthesize lookup = _lookup;
-(void)saveFrom:(NSManagedObjectContext *)current to:(NSManagedObjectContext *)parent
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserverForName:NSManagedObjectContextDidSaveNotification
object:current queue:nil
usingBlock:^(NSNotification *notification)
[parent mergeChangesFromContextDidSaveNotification:notification];
];
NSError *error;
if (![current save:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
[dnc removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:current];
- (NSManagedObject *)saveObject:(NSManagedObject *)object toContext:(NSManagedObjectContext *)moc
NSUndoManager *docUndoMgr = [moc undoManager];
[docUndoMgr beginUndoGrouping];
NSManagedObject *object2 = [self copyObject:object toContext:moc parent:nil];
[moc processPendingChanges];
[docUndoMgr endUndoGrouping];
return object2;
- (NSManagedObject *)copyObject:(NSManagedObject *)object
toContext:(NSManagedObjectContext *)moc
parent:(NSString *)parentEntity;
NSError *error = nil;
NSString *entityName = [[object entity] name];
NSManagedObject *newObject = nil;
if ([moc objectRegisteredForID:object.objectID])
newObject = [moc objectWithID:object.objectID];
else
newObject = [NSEntityDescription
insertNewObjectForEntityForName:entityName
inManagedObjectContext:moc];
if (![moc save:&error])
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
[[self lookup] setObject:newObject forKey:[object objectID]];
NSArray *attKeys = [[[object entity] attributesByName] allKeys];
NSDictionary *attributes = [object dictionaryWithValuesForKeys:attKeys];
[newObject setValuesForKeysWithDictionary:attributes];
id oldDestObject = nil;
id temp = nil;
NSDictionary *relationships = [[object entity] relationshipsByName];
for (NSString *key in [relationships allKeys])
NSRelationshipDescription *desc = [relationships valueForKey:key];
NSString *destEntityName = [[desc destinationEntity] name];
if ([destEntityName isEqualToString:parentEntity]) continue;
if ([desc isToMany])
NSMutableSet *newDestSet = [NSMutableSet set];
for (oldDestObject in [object valueForKey:key])
temp = [[self lookup] objectForKey:[oldDestObject objectID]];
if (!temp)
temp = [self copyObject:oldDestObject
toContext:moc
parent:entityName];
[newDestSet addObject:temp];
[newObject setValue:newDestSet forKey:key];
else
oldDestObject = [object valueForKey:key];
if (!oldDestObject) continue;
temp = [[self lookup] objectForKey:[oldDestObject objectID]];
if (!temp && ![destEntityName isEqualToString:parentEntity])
temp = [self copyObject:oldDestObject
toContext:moc
parent:entityName];
[newObject setValue:temp forKey:key];
return newObject;
@end
【讨论】:
以上是关于如何在其他 NSManagedObjectContext 中插入 NSManagedObject?的主要内容,如果未能解决你的问题,请参考以下文章
NSFetchedResultsController、NSManagedObjectContextDidSaveNotification 和 MagicalRecord 的舞蹈
IOS CoreData,使用哪个 NSManagedObjectContextConcurrencyType,为啥?
最佳实践 - iOS 中的 NSManagedObjectContextObjectsDidChangeNotification
从另一个 NSManagedObjectContext 获取 NSManagedObject(引用相同的 NSPersistentStoreCoordinator)