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];
}
Более информативный отчет об ошибках может помочь вам в устранении неполадок.