代码之家  ›  专栏  ›  技术社区  ›  kiyoshi

Iphone核心数据在保存时崩溃

  •  14
  • kiyoshi  · 技术社区  · 17 年前

    我目前正在使用核心数据编写一个Iphone应用程序,我得到了一个 EXC_BAD_ACCESS [managedObjectContext保存:&error]代码行期间出错。只有在修改某些字段后才会发生此崩溃。更具体地说,我的实体有两个字符串字段(大约10个字段中的两个),它们从模式视图控制器(如文本编辑器)的返回中获取值。崩溃也只有在编辑这些字段后才会发生,我第一次在其中输入值时效果良好。

    我之所以使用字符串和格式构造函数,只是因为我试图复制构造。。。不确定这是否会自动发生?我想可能会保留/释放那些字符串(这两个字符串来自模态视图控制器)中的消息,这些字符串在模态视图控制器被解除时被释放。我猜不会,因为它仍然不起作用。

    下面是正在崩溃的代码部分:

            - (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_访问必须在保存至少足够远以存储在持久存储中之后发生。

    如果我注释掉保存行,代码现在运行正常。但在我关闭并退出后它不会保存。如果在我的根视图控制器WillDisplay函数中运行保存行,它将抛出相同的EXC\u BAD\u访问错误。控制台除了EXC\u BAD\u访问之外没有说任何其他内容 如果我进行回溯,我会得到:

    #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文件,该文件是MessageView所属的类)

    只有当我将EditorViewController显示为模式视图,然后返回时,它才会崩溃。

    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:@""]];
    }
    
    7 回复  |  直到 17 年前
        1
  •  23
  •   spnkr    5 年前

    只有在对托管对象的更改(插入、更新、删除)挂起时,才能保证从上下文保留对该对象的访问权。只要调用save:,就可能丢失对托管对象的引用。

    当设置setRetainsRegisteredObjects时停止获取错误:是,您可能引入了内存管理问题,因为您正在将托管对象的生存期设置为依赖于托管对象上下文的生存期。如果你在整个应用程序中传递你的上下文,如果你有一个大的对象层次结构,这可能会变得相当大。

    您可以在以下Apple文档中阅读更多内容: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/MO_Lifecycle.html

        2
  •  10
  •   Bot    14 年前

    解决了问题,但我不确定是否解决了真正的根本原因。当我添加这一行时,错误被消除了:

    [managedObjectContext setRetainsRegisteredObjects:YES];
    

    到创建managedObjectContext的位置。所以我想这与保留计数有关。我猜,当模态视图出现时,可能会部分或暂时释放实例变量,或者其他什么?我不知道。在任何情况下,这个错误都被消除了,程序现在运行正常。

        3
  •  4
  •   Rog    15 年前

    为了帮助其他有相同问题的人,并加强Steff在上面的回答,此错误的可能原因是您试图发布NSManagedObject。

        4
  •  0
  •   Michael Sharek    17 年前

    我在iPhone上看到了许多关于CoreData的有趣行为,这些行为通过在iPhone模拟器中重置内容和设置得以解决。

        5
  •  0
  •   Steff    16 年前

    我知道这是一个老掉牙的问题,但我也有同样的问题,所以我想我应该加上我解决问题的方法,我的问题是由于在模态视图中手动释放托管对象造成的,我删除了释放调用,一切正常:)根据文档,无论如何,您不应该手动尝试释放托管对象,因为上下文将处理所有这些。这就是我的经验,在代码中搜索过度释放的值。

        6
  •  0
  •   tvanfosson    14 年前

    必须将FRC缓存设置为零

        7
  •  0
  •   Khurram Ali    13 年前

    if ( message == nil ) {
        message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
    } else {
        NSError *error = nil;
        message = (MailMessage *)[managedObjectContext existingObjectWithID:[message objectID] error:&error];
    }