CoreData: сбой приложения при удалении последнего созданного экземпляра - PullRequest
0 голосов
/ 01 июня 2010

У меня есть приложение с 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];

редактировать: Я нашел свою ошибку. Я делал сравнение для каждого образцаДата, как это:

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 ]

1 голос
/ 01 июня 2010

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

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

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

[newSampleList setSampleSet:newSampleSet];

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

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

0 голосов
/ 01 июня 2010

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

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

...