iPhone EXC_BAD_ACCESS на объекте после изменения контроллера представления в панели вкладок - PullRequest
0 голосов
/ 19 июля 2011

Приложение для моего iPhone представляет собой контроллер панели вкладок, загружающий 3 контроллера навигации: для первого представления - UIViewController, а для второго и третьего представлений - UITableViewController.

Во всех моих приложениях я обращаюсь к объекту«Автомобиль» из Core Data, который я храню в приложении делегата.После изменения первого вида панели управления моей панели вкладок я постоянно получаю EXC_BAD_ACCESS при доступе к объекту в 3 контроллере навигации (настройки).Отладчик показывает ошибку на @synthesize userCar=_userCar;.

Странная часть, когда я изменяю в моем приложении делегировать выбранный индекс моей панели вкладок, это работает.Поэтому, когда он загружает значение по умолчанию (index = 0), когда я захожу в представление настроек (index = 2), происходит сбой, но если я сначала загружаю представление настроек, то мое приложение все время работает отлично.

Сбой:

// Display the window with the tab bar.
[self.window addSubview:[self.tabBarController view]];
[self.window makeKeyAndVisible];

Не падает, если загружается в класс MyAppDelegate:

// Loads the 3 view (Settings) to avoid crash...
[self.tabBarController setSelectedIndex:2];

// Display the window with the tab bar.
[self.window addSubview:[self.tabBarController view]];
[self.window makeKeyAndVisible];

Поэтому я не понимаю, когда я возвращаю имя NIB и имя класса вмой MainWindow.xib (где у меня есть контроллер панели вкладок и т. д.), как это было раньше, он снова работает отлично.Я попытался очистить проект, перезапустить Xcode и удалить приложение с симулятора и устройства, но ничего не работает.

Есть идеи?Спасибо!

ОБНОВЛЕНИЕ 1

Итак, я объявляю свой автомобильный объект вот так @property (nonatomic, retain) Car *userCar; во всех моих контроллерах вида.

Затем, чтобы получить текущийавтомобиль, тот, который выбрал пользователь, я делаю это:

// Get the latest user car selected.
self.userCar = [EcoAppAppDelegate userCar];

Затем у моего делегата приложения есть 2 функции, которые позволяют мне играть с автомобилем, если пользователь создает новый, он автоматически сохраняется, если в настройках выберите другой автомобиль, предварительно выбранный, он также сохраняет его.В файле .m:

+ (Car *)userCar;
+ (void)setUserCar:(Car *)newCar;

В файле приложения делегата .m:

// On top of the file.
static Car *_userCar;

#pragma mark - Static functions

+ (Car *)userCar
{
    return _userCar;
}

+ (void)setUserCar:(Car *)newCar
{
    if (_userCar != newCar) {
        if (newCar != nil) {
            [_userCar release];
            _userCar = nil;
            _userCar = [newCar retain];
        }
        else {
            [_userCar release];
            _userCar = nil;
        }
    }
}

Последний фрагмент кода, когда я получаю автомобиль из базовых данных, я делаю этотаким образом (при запуске приложения, например, в приложении делегат didFinishLaunchingWithOptions):

// Load the car.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];

// Set predicate and sort orderings...
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"selected = 1"];
[fetchRequest setPredicate:predicate];

// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (mutableFetchResults != nil && [mutableFetchResults count] > 0) {
    // Get the car selected.
    _userCar = (Car *)[mutableFetchResults objectAtIndex:0];
}
else {
    // Handle error.
    _userCar = nil;
}

// Memory management.
[fetchRequest release];
[mutableFetchResults release];

1 Ответ

1 голос
/ 19 июля 2011

Я считаю, что основная проблема заключается в том, что объект автомобиля, который вы получаете из базовых данных, не сохраняется. Это действительный объект в самом начале программы, но как только все завершает загрузку, автомобильный объект автоматически освобождается.

Это можно исправить, изменив код coredata на:

// Execute the fetch -- create a mutable copy of the result.
NSError *error = nil;
NSArray *fetchResults = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchResults != nil && [fetchResults count] > 0) {
    // Get the car selected.
    _userCar = (Car *)[[fetchResults objectAtIndex:0] retain];
} else {
    // Handle error.
    _userCar = nil;
}

Обратите внимание на retain. Кроме того, нет причин создавать изменяемые копии результатов выборки.

...