CoreData DetailTableView BAD_ACCESS Ошибка - PullRequest
       17

CoreData DetailTableView BAD_ACCESS Ошибка

3 голосов
/ 12 августа 2011

Может быть, я не собираюсь показывать детали для выбранной строки с помощью CoreData, но я не могу понять, почему я получаю ошибку "BAD_ACCESS".Я погуглил и не могу найти то, что ищу.

В основном я использую CoreData для заполнения данных для табличного представления.Он извлекает все атрибуты заголовка для всех сущностей.Когда пользователь нажимает на строку, у меня появляется подробный вид, который должен показать описание для этой сущности.Я думаю, что мне нужно сделать новый NSManagedObjectContext и новую NSEntityDescription для нового NSFetchRequest в моем DetailViewController, а затем использовать NSPredicate, чтобы сказать «где название = [пользователь выбрал заголовок]».Я получаю сообщение об ошибке при выборе строки.См. Код:

- (void)viewDidLoad
{
    // Do any additional setup after loading the view from its nib.

    // Get the objects from Core Data database
    Caregiver_Activity_GuideAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];
    NSEntityDescription *entityDescription = [NSEntityDescription
                                              entityForName:@"Definition"
                                              inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDescription];

    NSPredicate *pred = [NSPredicate predicateWithFormat:@"(title = %@)", self.title];
    [request setPredicate:pred];

    NSError *error;
    NSArray *objects = [context executeFetchRequest:request error:&error];
    if (objects == nil) {
        NSLog(@"There was an error!");
        // Do whatever error handling is appropriate
    }

    for (NSManagedObject *oneObject in objects) {
        [definitionDescriptionTextView setText:[oneObject valueForKey:@"desc"]];
    }

    [objects release];
    [request release];

    [super viewDidLoad];
}

Я комментирую этот код, и все работает.Но когда я пытаюсь отладить с точками останова, ничего не ловит.Так что я в замешательстве.

Я знаю, что CoreData, вероятно, излишне для того, что я делаю, но для меня это учебное приложение.

РЕДАКТИРОВАТЬ: я не включил, что я 'm, используя базу данных sqlite, которая предварительно заполнена объектами.

Вы также можете загрузить мой проект на my github page .

1 Ответ

1 голос
/ 12 августа 2011

Обычно, с интерфейсом Master-Detail, поддерживаемым Базовыми данными, вы не выбираете для представления Подробности.

Когда вы выбираете строку в главном табличном представлении, вы выбираете конкретный экземпляр управляемого объекта. Затем вы передаете этот экземпляр управляемого объекта в подробный вид. Нет необходимости повторно выбирать объект, выбранный в представлении таблицы.

Хороший пример этого - приложение «Контакты». Главный табличный вид будет списком объектов Contact (с отображением имени). Когда вы выбираете строку, главный контроллер табличного представления берет конкретный объект Contact, связанный с выбранной строкой, а затем передает его в контроллер представления Detail, который затем заполняет Detail просмотр с использованием данных, взятых из свойств переданного объекта Contact.

Итак, весь блок кода, в котором возникает ошибка, не нужен.

Однако немедленная ошибка в этом коде заключается в том, что вы освобождаете объект, который не создали. В этой строке:

 NSArray *objects = [context executeFetchRequest:request error:&error];

... вы не создаете экземпляр NSArray с помощью метода init, new или create. Вместо этого вы просто получаете автоматически выпущенный экземпляр NSArray, созданный и возвращенный экземпляром context NSManagedObjectContext. Когда вы отпускаете объект, который вы не создали здесь:

 [objects release];

... вы вызвали аварию.

И наоборот, вы создаете NSFetchRequest здесь:

 NSFetchRequest *request = [[NSFetchRequest alloc] init];

... потому что вы использовали init, поэтому вы должны сбалансировать это с:

[request relwase];

Кстати, этот тип кода не следует вводить в viewDidLoad, поскольку метод вызывается только при первом чтении представления из файла пера на диске. Это гарантированно произойдет только один раз, поскольку представление может остаться в памяти, когда пользователь переключается на другое представление. Вместо этого поместите код, который должен запускаться каждый раз, когда представление появляется в viewWillAppear.

...