0

当应用程序进入后台时,我的 View Controller 类被释放。我正在使用ARC。

我有一个 UIViewController,它在应用程序变为活动状态并执行方法时订阅通知。但是一旦应用程序在后台运行大约 30 秒然后恢复,应用程序就会崩溃,并显示“发送到已释放实例的消息”。

启用 Zombie 对象表明 View Controller 本身就是 Zombie。

谢谢!

我的视图控制器的实例化(在 AppDelegate 中):

UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyBoard instantiateViewControllerWithIdentifier:@"MyViewController"];

AppDelegate 中的前台通知:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationForegrounded object:self];
}

视图控制器中的前台通知:

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resumeForeground) name:kNotificationForegrounded object:nil];
}

我尝试在 AppDelegate 中创建一个强引用,但视图控制器仍然被释放:

@property (strong, nonatomic) MyViewController *myViewController;

我尝试将视图控制器添加到数组并在 AppDelegae 中对数组进行强引用,但仍然得到相同的结果:

@property (strong, nonatomic) NSMutableArray *viewControllers;
//...
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyBoard instantiateViewControllerWithIdentifier:@"MyViewController"];
self.viewControllers = [[NSMutableArray alloc] init];
[self.viewControllers addObject:myViewController];
4

2 回答 2

1

这里有两个问题 - 您的应用程序委托没有正确管理其对象所有权,并且视图控制器没有自行清理。

每次执行代码来实例化. 时,您都会通过替换为新实例MyViewController来释放所有现有视图控制器的所有权。self.viewControllers只分配一次,并根据需要添加和删除对象。此外,您永远不会使用您的强属性,只使用同名的本地实例变量。您可能实际上应该确保您希望此代码一遍又一遍地运行(鉴于您描述的症状和信息,我假设它是)。

此外,在MyViewController, 中实施dealloc(如果您已经实施,则添加到其中):

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
于 2013-03-20T16:29:55.073 回答
0

问题:

  1. MyViewController每次MyViewController *myViewController = [storyBoard instantiateViewControllerWithIdentifier:@"MyViewController"];调用时都会重新实例化。

  2. 使用 ARC,看起来当应用程序进入前台时,已经完成了一些清理工作。

  3. 当应用程序移动到前台时,@dealloc前台通知同时从两个不同的线程调用,因此当在通知上执行选择器方法时,(无引用)视图控制器已被标记为或将被释放。

解决方案:

正如@Carl 建议的那样,我添加了[[NSNotificationCenter defaultCenter] removeObserver:self];除了不是 in 之外@dealloc,而是在视图控制器使用完成的较早时间点。我认为在重新实例化之前就这样做也可以。

于 2013-03-21T17:57:21.733 回答