在标签栏中更改视图控制器后,对象上的iPhone EXC_BAD_ACCESS

时间:2011-07-19 00:25:45

标签: iphone exc-bad-access accessor

我的iPhone应用程序是一个标签栏控制器,加载3个导航控制器:第一个视图是UIViewController,第二个和第三个视图是UITableViewController。

在我的所有应用程序中,我访问来自Core Data的对象“Car”,我将其存储在app delegate中。更改我的标签栏的第一个导航控制器视图后,我在访问3导航控制器中的对象(设置)时始终进入EXC_BAD_ACCESS。调试器在@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];

所以我不明白,当我将我的MainWindow.xib(我的标签栏控制器等)中的NIB名称和类名更改回之前的状态时,它再次完美地运行。我尝试清理项目,重新启动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;

在app delegate .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;
        }
    }
}

最后一段代码,当我从Core Data获取汽车时,我这样做(在应用程序启动时,例如在app delegate 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 个答案:

答案 0 :(得分:1)

我认为主要问题是您从核心数据获取的汽车对象未被保留。它在程序的最开始是一个有效的对象,但是一旦所有内容都完成加载,汽车对象就会被自动释放。

您可以通过将您的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。此外,没有理由制作获取结果的可变副本。