Magical Record 检测到默认上下文没有变化
Magical Record detect no changes in default context
我正在为我的应用程序使用 Magical Record,因此我可以利用他们的核心数据堆栈,该堆栈应该自动将我在工作上下文(核心数据线程)中的更改传播到默认上下文(主线程的)。我一直在核心数据写入队列中创建和更新我的对象,一切正常。
然后我 运行 解决了这个问题,即 Magical Record 能够将我的更改保存在我的工作上下文中,但是当它尝试保存到默认上下文时,它没有检测到任何更改,因此不会保存.
我哪里做错了?在我的应用程序的其余部分,我以几乎相同的方式创建和更新并且它有效。请帮忙。谢谢!
相关代码如下:
所有这些更改后未检测到任何更改:
dispatch_async(CoreDataWriteQueue(), ^{
if (self.person) {
FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
[newPerson addGroup:localGroup];
}
[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait];
});
我也尝试过 saveWithBlock 方法,但没有成功:
dispatch_async(CoreDataWriteQueue(), ^{
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
if (self.person) {
FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
[newPerson addGroup:localGroup];
}
}];
});
这里是我创建个人和群组对象的地方:
dispatch_async(CoreDataWriteQueue(), ^{
FTPerson *newPerson = [[FTPerson alloc] initWithName:@"test" andInitialTrainingImages:@[[UIImage imageNamed:@"test.jpg"]]];
});
dispatch_async(CoreDataWriteQueue(), ^{
FTGroup *newGroup = [[FTGroup alloc] init];
[self setGroup:newGroup];
});
还有初始化方法:
人
- (id)initWithName:(NSString *)name andInitialTrainingImages:(NSArray *)images {
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
self = [FTPerson MR_createInContext:context];
self.name = name;
self.id = [[NSUUID UUID] UUIDString];
self.objectIDString = [[self.objectID URIRepresentation] absoluteString];
self.trainingImages = [[NSMutableArray alloc] init];
[context MR_saveToPersistentStoreAndWait];
return self;
}
组
- (id)init {
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
self = [FTGroup MR_createInContext:context];
self.id = [[NSUUID UUID] UUIDString];
self.didFinishTraining = NO;
self.didFinishProcessing = NO;
self.photosTrained = @(0);
self.lastProcessedDate = [NSDate date];
[context MR_saveToPersistentStoreAndWait];
return self;
}
固定
所以问题最终与魔法记录无关。
我错误地将对象添加到我的核心数据 NSSet。与其将其设为 NSMutableSet 并执行 addObject:,我应该:
NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"];
[mutablePhotos addObject:photo];
我认为您在处理 Core Data 时不应该使用自己的调度队列。 NSManagedObjectContext
上的 -performBlock:
方法的全部要点是 Core Data 负责在正确的队列上执行提供的块。
现在回答你的问题。首先,您使用的是 MagicalRecord 2.x 还是 3.0?如果 2.x,请确保使用 develop 分支,或者获取最新版本(此时为 v2.3beta5)。最新的dev和release分支有很多改进。
其次,我认为在使用 Core Data 进行多线程处理时做两件事很重要:
- 始终通过编辑方案和设置
-com.apple.CoreData.ConcurrencyDebug 1
打开并发调试
- 始终非常明确地说明您要使用的上下文。 MagicalRecord 团队不再推荐
-MR_contextForCurrentThread
方法是有原因的。修改您的创建方法以将 NSManagedObjectContext
作为参数,这样就不会怀疑创建它的上下文。
尝试进行以下更改:
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
if (self.person) {
FTPerson *localPerson = [self.person MR_inContext:localContext];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages inContext:localContext];
FTGroup *localGroup = [self.group MR_inContext:localContext];
[newPerson addGroup:localGroup];
}
}];
人:
- (id)initWithName:(NSString *)name andInitialTrainingImages:(NSArray *)images inContext:(NSManagedObjectContext*)context {
self = [FTPerson MR_createInContext:context];
self.name = name;
self.id = [[NSUUID UUID] UUIDString];
self.objectIDString = [[self.objectID URIRepresentation] absoluteString];
self.trainingImages = [[NSMutableArray alloc] init];
[context MR_saveToPersistentStoreAndWait];
return self;
}
对于 Person,我注意到您传入了一个图像数组,但您将一个空数组分配给了新的 person 实体。你是要那样做吗?
群组:
-(id)initWithContext:(NSManagedObjectContext*)context {
self = [FTGroup MR_createInContext:context];
self.id = [[NSUUID UUID] UUIDString];
self.didFinishTraining = NO;
self.didFinishProcessing = NO;
self.photosTrained = @(0);
self.lastProcessedDate = [NSDate date];
[context MR_saveToPersistentStoreAndWait];
return self;
}
所以问题最终与魔法记录无关。我错误地将对象添加到我的核心数据 NSSet。与其将其设为 NSMutableSet 并执行 addObject:,我应该:
NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"];
[mutablePhotos addObject:photo];
我正在为我的应用程序使用 Magical Record,因此我可以利用他们的核心数据堆栈,该堆栈应该自动将我在工作上下文(核心数据线程)中的更改传播到默认上下文(主线程的)。我一直在核心数据写入队列中创建和更新我的对象,一切正常。
然后我 运行 解决了这个问题,即 Magical Record 能够将我的更改保存在我的工作上下文中,但是当它尝试保存到默认上下文时,它没有检测到任何更改,因此不会保存.
我哪里做错了?在我的应用程序的其余部分,我以几乎相同的方式创建和更新并且它有效。请帮忙。谢谢!
相关代码如下:
所有这些更改后未检测到任何更改:
dispatch_async(CoreDataWriteQueue(), ^{
if (self.person) {
FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
[newPerson addGroup:localGroup];
}
[[NSManagedObjectContext MR_contextForCurrentThread] MR_saveToPersistentStoreAndWait];
});
我也尝试过 saveWithBlock 方法,但没有成功:
dispatch_async(CoreDataWriteQueue(), ^{
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
if (self.person) {
FTPerson *localPerson = [FTPerson fetchWithID:self.person.id];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages];
FTGroup *localGroup = [FTGroup fetchWithID:self.group.id];
[newPerson addGroup:localGroup];
}
}];
});
这里是我创建个人和群组对象的地方:
dispatch_async(CoreDataWriteQueue(), ^{
FTPerson *newPerson = [[FTPerson alloc] initWithName:@"test" andInitialTrainingImages:@[[UIImage imageNamed:@"test.jpg"]]];
});
dispatch_async(CoreDataWriteQueue(), ^{
FTGroup *newGroup = [[FTGroup alloc] init];
[self setGroup:newGroup];
});
还有初始化方法:
人
- (id)initWithName:(NSString *)name andInitialTrainingImages:(NSArray *)images {
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
self = [FTPerson MR_createInContext:context];
self.name = name;
self.id = [[NSUUID UUID] UUIDString];
self.objectIDString = [[self.objectID URIRepresentation] absoluteString];
self.trainingImages = [[NSMutableArray alloc] init];
[context MR_saveToPersistentStoreAndWait];
return self;
}
组
- (id)init {
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
self = [FTGroup MR_createInContext:context];
self.id = [[NSUUID UUID] UUIDString];
self.didFinishTraining = NO;
self.didFinishProcessing = NO;
self.photosTrained = @(0);
self.lastProcessedDate = [NSDate date];
[context MR_saveToPersistentStoreAndWait];
return self;
}
固定
所以问题最终与魔法记录无关。 我错误地将对象添加到我的核心数据 NSSet。与其将其设为 NSMutableSet 并执行 addObject:,我应该:
NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"];
[mutablePhotos addObject:photo];
我认为您在处理 Core Data 时不应该使用自己的调度队列。 NSManagedObjectContext
上的 -performBlock:
方法的全部要点是 Core Data 负责在正确的队列上执行提供的块。
现在回答你的问题。首先,您使用的是 MagicalRecord 2.x 还是 3.0?如果 2.x,请确保使用 develop 分支,或者获取最新版本(此时为 v2.3beta5)。最新的dev和release分支有很多改进。
其次,我认为在使用 Core Data 进行多线程处理时做两件事很重要:
- 始终通过编辑方案和设置
-com.apple.CoreData.ConcurrencyDebug 1
打开并发调试
- 始终非常明确地说明您要使用的上下文。 MagicalRecord 团队不再推荐
-MR_contextForCurrentThread
方法是有原因的。修改您的创建方法以将NSManagedObjectContext
作为参数,这样就不会怀疑创建它的上下文。
尝试进行以下更改:
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext){
if (self.person) {
FTPerson *localPerson = [self.person MR_inContext:localContext];
[localPerson setName:self.nameField.text];
[localPerson trainWithImages:self.addedImages];
} else {
FTPerson *newPerson = [[FTPerson alloc] initWithName:self.nameField.text andInitialTrainingImages:self.addedImages inContext:localContext];
FTGroup *localGroup = [self.group MR_inContext:localContext];
[newPerson addGroup:localGroup];
}
}];
人:
- (id)initWithName:(NSString *)name andInitialTrainingImages:(NSArray *)images inContext:(NSManagedObjectContext*)context {
self = [FTPerson MR_createInContext:context];
self.name = name;
self.id = [[NSUUID UUID] UUIDString];
self.objectIDString = [[self.objectID URIRepresentation] absoluteString];
self.trainingImages = [[NSMutableArray alloc] init];
[context MR_saveToPersistentStoreAndWait];
return self;
}
对于 Person,我注意到您传入了一个图像数组,但您将一个空数组分配给了新的 person 实体。你是要那样做吗?
群组:
-(id)initWithContext:(NSManagedObjectContext*)context {
self = [FTGroup MR_createInContext:context];
self.id = [[NSUUID UUID] UUIDString];
self.didFinishTraining = NO;
self.didFinishProcessing = NO;
self.photosTrained = @(0);
self.lastProcessedDate = [NSDate date];
[context MR_saveToPersistentStoreAndWait];
return self;
}
所以问题最终与魔法记录无关。我错误地将对象添加到我的核心数据 NSSet。与其将其设为 NSMutableSet 并执行 addObject:,我应该:
NSMutableSet *mutablePhotos = [self mutableSetValueForKey:@"photos"]; [mutablePhotos addObject:photo];