我目前正在使用Core Data编写Iphone应用程序,并且在[managedObjectContext save:&& error]代码行中出现EXC_BAD_ACCESS
错误。只有在修改某些字段后才会发生此崩溃。更具体地说,我的实体有两个字符串字段(大约10个字段中的字段),它们从模式视图控制器(如文本编辑器)的返回中获取它们的值。崩溃也只发生在编辑这些字段之后,第一次将值放入其中时工作正常。
我有格式构造函数的字符串只是字符串的原因是因为我试图复制构造...不确定是否自动发生?想到可能会保留/释放来自那些字符串的消息(这两个来自模态视图控制器),在解雇模态视图控制器或其他东西时被释放。但不要猜测,因为它仍然不起作用。
以下是崩溃的代码部分:
[EDITED]
- (void)actionSheet:(UIActionSheet *)modalView clickedButtonAtIndex: (NSInteger)buttonIndex
switch(buttonIndex) {
case 0: {
if(message == nil) {
message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
}
message.toString = txtTo.text;
message.fromString = txtFrom.text;
message.subjectString = txtSubject.text;
message.backgroundColor = [NSNumber numberWithInt:[bgColor intValue]];
message.textArray = [NSString stringWithFormat:@"%@", stringTextArray];
message.htmlString = [NSString stringWithFormat:@"%@", stringHTML];
message.timeStamp = [NSDate date];
message.statusCode = [NSNumber numberWithInt:0];
NSError *error = nil;
if (![message.managedObjectContext save:&error]) {
abort();
}
break;
}
case 1: {
break;
}
}
if(buttonIndex != modalView.cancelButtonIndex) {
[webViewBody loadHTMLString:@"<html><head></head><body></body></html>" baseURL:[NSURL URLWithString:@""]];
[self.navigationController popToRootViewControllerAnimated:YES];
}
}
这是崩溃日志:
Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x00000015 Crashed Thread: 0 Thread 0 Crashed: 0 libobjc.A.dylib 0x30011940 objc_msgSend + 20 1 CoreData 0x367f7d3e -[NSKnownKeysDictionary1 dealloc] + 82 2 CoreData 0x367f7cda -[NSKnownKeysDictionary1 release] + 34 3 CoreData 0x3687eec4 -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] + 40 4 CoreData 0x36821030 -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] + 16 5 CoreData 0x368205f2 -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] + 958 6 CoreData 0x368133bc -[NSManagedObjectContext save:] + 412 7 Decome 0x0001fdd6 -[CreateMessageViewController actionSheet:clickedButtonAtIndex:] (CreateMessageViewController.m:163) 8 UIKit 0x30a6cbd8 -[UIActionSheet(Private) _buttonClicked:] + 256 9 CoreFoundation 0x30256dd4 -[NSObject performSelector:withObject:withObject:] + 20 10 UIKit 0x3096e0d0 -[UIApplication sendAction:to:from:forEvent:] + 128 11 UIKit 0x3096e038 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32 12 UIKit 0x3096e000 -[UIControl sendAction:to:forEvent:] + 44 13 UIKit 0x3096dc58 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 528 14 UIKit 0x309a6e9c -[UIControl touchesEnded:withEvent:] + 452 15 UIKit 0x309a60d4 -[UIWindow _sendTouchesForEvent:] + 520 16 UIKit 0x309a5464 -[UIWindow sendEvent:] + 108 17 UIKit 0x30936e3c -[UIApplication sendEvent:] + 400
感谢任何帮助,谢谢。
更新:此外,即使程序崩溃,当我打开它时,数据已正确保存。所以EXC_BAD_ACCESS必须在保存至少足够存储到我认为的持久存储中之后发生。
如果我注释掉保存行,代码现在运行正常。但是在我关闭并退出后它并没有保存。如果我在Root View Controllers willAppear函数中运行保存行,则会抛出相同的EXC_BAD_ACCESS错误。除了EXC_BAD_ACCESS之外,控制台没有说任何其他内容 如果我做回溯,我会得到:
#0 0x30011940 in objc_msgSend () #1 0x367f7d44 in -[NSKnownKeysDictionary1 dealloc] () #2 0x367f7ce0 in -[NSKnownKeysDictionary1 release] () #3 0x3687eeca in -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] () #4 0x36821036 in -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] () #5 0x368205f8 in -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] () #6 0x368133c2 in -[NSManagedObjectContext save:] () #7 0x0000314e in -[RootViewController viewWillAppear:] (self=0x11b560, _cmd=0x3014ecac, animated=1 '\001') at /Users/inckbmj/Desktop/iphone/Decome/Classes/RootViewController.m:85
很抱歉,之前的代码格式不正确。当这个视图控制器被创建时,如果它不是一个新的“消息”,它将传递一个从fetchedResultsController获得的消息对象,如下所示:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MailMessage *aMessage = (MailMessage *)[fetchedResultsController objectAtIndexPath:indexPath];
[messageView loadMessage:aMessage viewOnly:NO usingTemplate:NO];
messageView.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:messageView animated:YES];
}
(第一组代码来自MessageViewController.m文件,它是messsageView的类)
如果我将EditorViewController作为模态视图呈现然后返回,它只会崩溃。 即使我将textArray和htmlString行(这是模态视图影响的唯一内容)更改为:
message.textArray = @"HELLO";
message.htmlString = @"HELLO";
它仍然崩溃。如果我对这两行都进行评论,那么它就不会崩溃。
因此,如果我提出一个模态视图然后尝试编辑我的NSOManagedObject的textArray或htmlString字段,它似乎崩溃了......
以下是我提出观点的地方:
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event {
if(!viewOnly) {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: txtTo];
location = [touch locationInView: webViewBody];
if(CGRectContainsPoint(webViewBody.bounds, location)) {
[editor loadTextArrayString:stringTextArray];
[self presentModalViewController:editor animated:YES];
}
}
}
我解雇的地方:
-(void)returnWithTextArray:(NSString *)arrayString HTML:(NSString *)html bgColor:(NSNumber *)numColor {
[self dismissModalViewControllerAnimated:YES];
self.stringTextArray = [NSString stringWithFormat:@"%@", arrayString];
self.stringHTML = [NSString stringWithFormat:@"%@", html];
self.bgColor = [NSNumber numberWithInt:[numColor intValue]];
[webViewBody loadHTMLString:self.stringHTML baseURL:[NSURL URLWithString:@""]];
}
答案 0 :(得分:23)
只要对该对象进行了更改(插入,更新,删除),您就只能保证从上下文中保留对托管对象的访问权限。只要您调用save:,就会丢失对托管对象的引用。
当您在设置setRetainsRegisteredObjects:YES时停止获取错误时,您可能已经引入了内存管理问题,因为您将托管对象的生存期设置为依赖于托管对象上下文的生存期。如果您在整个应用程序中传递上下文,如果您有一个大的对象层次结构,这可能会变得相当大。
您可以在此处阅读Apple文档中的更多内容:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMemory.html。
答案 1 :(得分:8)
解决了这个问题虽然我不确定我是否正在解决实际的根本原因。当我添加这一行时,错误被消除了:
[managedObjectContext setRetainsRegisteredObjects:YES];
我在哪里创建managedObjectContext。所以我想这与保留计数有关。我猜测可能部分或临时释放实例变量或者在呈现模态视图时会发布什么?我不知道。在任何情况下,这个错误都被消除了,程序现在工作正常。
答案 2 :(得分:4)
只是为了帮助其他人遇到同样的问题,并加强上面的Steff响应,这个错误的可能原因是你试图释放一个NSManagedObject。
答案 3 :(得分:0)
我在iPhone上看到了很多有趣的行为,通过重置iPhone模拟器中的内容和设置解决了这些行为。
答案 4 :(得分:0)
我知道这是一个老人,但我有同样的问题,所以我想加上我的问题,我是如何解决问题的,我是在模态视图中手动释放托管对象引起的,我删除了发布调用并且一切工作正常:)根据文档,您不应该手动尝试并释放托管对象,因为上下文将照顾所有这些。无论如何,这是我的经验,在代码中搜索过度释放的值。
答案 5 :(得分:0)
您必须将FRC缓存设置为nil
答案 6 :(得分:0)
我通过确保提取对象解决了类似的问题,因此对于上面的示例:
if ( message == nil ) {
message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
} else {
NSError *error = nil;
message = (MailMessage *)[managedObjectContext existingObjectWithID:[message objectID] error:&error];
}