CoreData:删除最后创建的实例时应用程序崩溃

时间:2010-06-01 07:40:19

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

我有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信号。如果我重新启动它,那么我就可以毫无问题地删除“旧”sampleList。

之前,我遇到了以下问题:我无法显示自我启动应用程序后创建的sampleLists,因为它也崩溃了。我还收到了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];
}

2 个答案:

答案 0 :(得分:1)

根据NSEntityDescription的文档,

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

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

[newSampleList setSampleSet:newSampleSet];

newSampleList最终将自动释放,这会导致您在重新启动应用时有时会获得EXC_BAD_ACCESS。

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

答案 1 :(得分:0)

我喜欢使用以下方法来获取更具信息性的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];
}

更详细的错误报告可以帮助您进行故障排除。