【发布时间】:2012-08-07 05:45:41
【问题描述】:
我有一个非常烦人的问题,我似乎无法解决。
当我发送一条保存到核心数据的消息时,我有一个视图,完成后它会向数据库询问随机消息(句子)并将其保存到数据库中的另一行。
如果我对最后一部分进行硬编码,而不从数据库中获取数据,它可以正常工作,但只要我从数据库中获取随机行,它就会发疯。
在我的 AppDelegate.m 中:
- (void)save {
NSAssert(self.context != nil, @"Not initialized");
NSError *error = nil;
BOOL failed = [self.context hasChanges] && ![self.context save:&error];
NSAssert1(!failed,@"Save failed %@",[error userInfo]);
}
- (NSString*)selectRandomSentence
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Sentences" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSError *error = nil;
NSUInteger count = [self.context countForFetchRequest:request error:&error];
NSUInteger offset = count - (arc4random() % count);
[request setFetchOffset:offset];
[request setFetchLimit:1];
NSArray *sentenceArray = [self.context executeFetchRequest:request error:&error];
[request release];
return [[sentenceArray objectAtIndex:0] sentence];
}
- (NSManagedObjectContext *)context {
if (_managedObjectContext != nil)
return _managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self coordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
在我的 ChatController.m 中:
- (void)didRecieveMessage:(NSString *)message
{
[self addMessage:message fromMe:NO];
}
#pragma mark -
#pragma mark SendControllerDelegate
- (void)didSendMessage:(NSString*)text {
[self addMessage:text fromMe:YES];
}
#pragma mark -
#pragma mark Private methods
- (void)responseReceived:(NSString*)response {
[self addMessage:response fromMe:NO];
}
- (void)addMessage:(NSString*)text fromMe:(BOOL)fromMe {
NSAssert(self.repository != nil, @"Not initialized");
Message *msg = [self.repository messageForBuddy:self.buddy];
msg.text = text;
msg.fromMe = fromMe;
if (fromMe)
{
[self.bot talkWithBot:text];
}
[self.repository asyncSave];
[self.tableView reloadData];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:[self.buddy.messages count] - 1] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
在我的 OfflineBot.m 中:
- (void)talkWithBot:(NSString *)textFromMe
{
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[self didRecieveMessage:[delegate selectRandomSentence]];
}
- (void)didRecieveMessage:(NSString *)message
{
if ([self.delegate respondsToSelector:@selector(didRecieveMessage:)])
[self.delegate didRecieveMessage:message];
}
Repository.m
- (Message*)messageForBuddy:(Buddy*)buddy {
Message *msg = [self.delegate entityForName:@"Message"];
msg.source = buddy;
[self.delegate.managedObjectContext refreshObject:buddy mergeChanges:YES];
return msg;
}
- (void)asyncSave {
[self.delegate save];
}
错误:
2012-08-10 00:28:20.526 Chat[13170:c07] * 中的断言失败 -[AppDelegate 保存],/Users/paulp/Desktop/TestTask/Classes/AppDelegate.m:28 2012-08-10 00:28:20.527 Chat[13170:c07] * 由于未捕获而终止应用程序 异常'NSInternalInconsistencyException',原因:'保存失败 {type = 不可变字典,count = 2, 条目=> 1:{内容= "NSAffectedObjectsErrorKey"} = ( "(实体:句子;id:0x6b8bf10; 数据:)“)2:{内容= "NSUnderlyingException"} = CoreData 无法完成错误 '0x6b8bf10 ' }
我做错了什么?
更新 我指出了这一行的错误:
NSArray *sentenceArray = [self.context executeFetchRequest:request error:&error];
当我执行该行时,我得到了错误......那是在获取数据时。但是,将新数据保存到 Messages 实体时似乎出现了错误。随机句子是从句子中获取的。
在我将 asyncSave 方法更改为直接保存(因此不使用新线程)后,它会保存第一次聊天,但之后什么也没有。它死了。
更新
在我的didFinishLaunchingWithOptions 中使用它似乎一切正常:
[self.context setRetainsRegisteredObjects:YES];
据我所知,CodeData 对象模型上下文不会释放其对象,这似乎是添加和保存之间的问题。但为什么呢?
【问题讨论】:
-
Paul,在您的更新中,您提到您将错误定位到
executeFetchRequest调用,但在保存没有意义的上下文时发生错误。您是否有机会在应用程序中使用多个线程?这通常是NSInternalInconsistencyException的罪魁祸首 -
self.context 和 self.managedObjectContext 有什么区别。您似乎可以互换使用它们,这听起来不是一个好主意。
-
另外,您似乎没有使用 ARC,但您似乎没有正确管理您的内存。此错误通常意味着您从商店中删除了某些内容,但没有正确更新您的 MOC,或者您有多个线程与同一个 MOC 混淆。
-
Self.context 只不过是我的 AppDelegate 中的一个方法。我已经分析并检查了我的代码,但那里没有内存泄漏。如何确保我在同一个线程上?
-
...我更新了问题。另外,为了解释我的最后一条评论:我根本没有任何泄漏。构建时我也没有得到任何分析或警告。
标签: objective-c ios core-data nsmanagedobject nsmanagedobjectcontext