【问题标题】:CoreData : App crashes when deleting last instance createdCoreData:删除创建的最后一个实例时应用程序崩溃
【发布时间】:2011-02-26 05:45:47
【问题描述】:

我有一个 2 个标签的应用程序。在第一个中,我正在创建“Sample”和“SampleList”实体的对象。每个 sampleList 包含一个 ID 和一组样本。每个样本都包含一个日期和温度属性。

在第二个选项卡中,我在 tableView 中显示我的数据。我实现了

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

方法以删除 SampleLists。在我的xcdatamodel 中,我的 SampleList 和 Sample 之间关系的删除规则是 Cascade

我的问题是,当我尝试删除刚刚创建的 SampleList 时,应用程序崩溃并且我收到 EXC_BAD_ACCESS 信号。如果我重新启动它,那么我可以毫无问题地删除“旧”样本列表。

之前,我遇到了以下问题:我无法显示自启动应用程序以来创建的示例列表,因为它也崩溃了。我还收到了EXC_BAD_ACCESS 信号。实际上,该集合的最后一个样本的创建日期似乎是nil。如果我不发布我用来设置示例日期的 NSDate,我就不会有这个问题了......

如果有人可以帮助我找出可能导致我的麻烦的原因,那就太好了!!

这是我用来创建新实例的方法:

SampleList *newSampleList = (SampleList *)[NSEntityDescription insertNewObjectForEntityForName:@"SampleList" inManagedObjectContext:managedObjectContext];
[newSampleList setPatchID:patchID];
NSMutableSet *newSampleSet = [[NSMutableSet alloc] init];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

for (int i = 0; i < [byteArray count]; i=i+4, sampleCount++) {
  NSDateComponents *comps = [[NSDateComponents alloc] init];
  [comps setYear:year];
  [comps setMonth:month];
  [comps setDay:day];
  [comps setHour:hours];
  [comps setMinute:minutes];
  NSDate *sampleDate = [gregorian dateFromComponents:comps];

  Sample *newSample = (Sample *)[NSEntityDescription insertNewObjectForEntityForName:@"Sample" inManagedObjectContext:managedObjectContext];  

  [newSample setSampleDate:sampleDate];
  [newSample setSampleTemperature:[NSNumber numberWithInt:temperature]];

  [newSampleSet addObject:newSample];
  [comps release];
  //[sampleDate release];
 }

 [newSampleList setSampleSet:newSampleSet];
 // [newSampleSet release];

 NSError *error;
 if (![managedObjectContext save:&error]) {
  NSLog(@"Could not Save the context !!");
 }

 [gregorian release];

编辑: 我发现了我的错误。 我正在对每个 sampleDate 进行这样的比较:

NSDate *maxDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:0];
(...)
for (int i = 0; i < [byteArray count]; i=i+4, sampleCount++) {
    (...)
    if ([maxDate compare:sampleDate] == NSOrdredAscending){
        max = sampleDate;
    }

我应该去的地方:

if ([maxDate compare:sampleDate] == NSOrdredAscending){
    [maxDate release];
    maxDate = [sampleDate retain];
}

【问题讨论】:

    标签: iphone objective-c core-data memory-management exc-bad-access


    【解决方案1】:

    我喜欢使用如下方法来获得更丰富的 Core Data 错误报告:

    - (void) detailedStoreError:(NSError *)error {
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray *_detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if (_detailedErrors != nil && [_detailedErrors count] > 0) {
            for (NSError *_detailedError in _detailedErrors) {
                NSLog(@" DetailedError: %@", [_detailedError userInfo]);
            }
        }
        else {
            NSLog(@" %@", [error userInfo]);
        }
    }
    

    你可以这样使用它:

    NSError *error;
    if (![managedObjectContext save:&error]) {
        [self detailedStoreError:error];
    }
    

    提供更多信息的错误报告可能会帮助您进行故障排除。

    【讨论】:

    • 感谢您的建议,但我在保存上下文时没有任何错误。但现在我会这样做!
    【解决方案2】:

    根据NSEntityDescription 的文档,

    + (id)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context
    

    返回一个自动释放的对象。所以你不需要在之后发布它:

    [newSampleList setSampleSet:newSampleSet];
    

    newSampleList 最终会自动释放,这会导致您在重新启动应用时看到有时会收到 EXC_BAD_ACCESS。

    Apple 的memory management documentation 将为您提供最佳实践,以便您何时需要自己释放对象以及何时自动释放对象。

    【讨论】:

    • newSampleSet 是通过 alloc+init 创建的,然后由 newSampleList 再次保留,因此您需要执行 [newSampleSet release] 以平衡 alloc+init。当 newSampleList 自动释放时,它也会释放 newSampleSet。
    • 我肯定在内存管理方面做错了。我正在查看您指出的文档。我对 NSDate 做错了什么。事实上,我试图删除我的代码(和 xcdatamodel)中有关日期的所有内容,我的应用程序不再崩溃。我将更深入地研究这些日期和内存管理。
    • 所以内存管理文档链接很有用!谢谢
    • 没问题!我也花了一段时间才掌握了这一切。最新版本的 xcode 在 Build->Build and Analyze 下也有一个方便的工具。它使用 llvm-clang 静态分析您的代码,然后以漂亮的方式显示结果。试试看。
    猜你喜欢
    • 2012-02-02
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多