CoreData: сбой приложения при удалении последнего созданного экземпляра

У меня есть приложение с 2 вкладками. В первом из них я создаю объекты сущностей "Sample" и "SampleList". Каждый образец списка содержит идентификатор и набор образцов. Каждый образец содержит свойство даты и температуры.

На второй вкладке я отображаю свои данные в табличном представлении. Я реализовал

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

метод для того, чтобы удалить SampleLists. В моем xcdatamodel правило удаления для моих отношений между SampleList и Sample Cascade,

Моя проблема в том, что когда я пытаюсь удалить SampleList, который я только что создал, приложение вылетает, и я получаю EXC_BAD_ACCESS сигнал. Если я перезапущу его, то смогу без проблем удалить "старый" sampleList.

Раньше у меня была следующая проблема: я не мог отобразить образцы-списки, которые я создал с тех пор, как запустил приложение, потому что оно тоже зависало. Я получил также 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 ответа

Решение

Согласно документации для NSEntityDescription,

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

возвращает автоматически выпущенный объект. Так что вам не нужно выпускать его после:

[newSampleList setSampleSet:newSampleSet];

В конечном итоге newSampleList будет автоматически выпущен, что приводит к тому, что иногда вы получаете EXC_BAD_ACCESS при перезапуске приложения.

Документация Apple по управлению памятью предоставит вам лучшие рекомендации, когда вам нужно освободить объект самостоятельно и когда объекты автоматически освобождены.

Мне нравится использовать метод, подобный следующему, чтобы получить более информативный отчет об ошибках 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];
}

Более информативный отчет об ошибках может помочь вам в устранении неполадок.

Другие вопросы по тегам