我正在开发一个我正在重构的遗留应用程序,并且有一个我不理解的奇怪行为。
有一个UIViewController
调用CANoContentViewController
它有一个来自 Nib 的简单初始化代码:
+ (CANoContentViewController *)instantiateController {
CANoContentViewController *vc = [[CANoContentViewController alloc] initWithNibName:@"CANoContentViewController" bundle:[NSBundle mainBundle]];
DLog(@"Created CANoContentViewController %@", vc);
return vc;
}
然后,其他
UIViewController
如果没有要显示的内容,则显示它。这是代码:@property (nonatomic, weak) UIViewController *noContentViewController;
-(void)showOrDeleteNoContentIfNeeded{
if([self.proposals count] <= 0) { // Show No Content VC
self.noContentViewController = [CANoContentViewController instantiateController];
DLog(@"Set CANoContentViewController %@", self.noContentViewController);
self.noContentViewController.view.frame = self.view.bounds;
[self addChildViewController:self.noContentViewController];
[self.view addSubview:self.noContentViewController.view];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
} else {
[self.noContentViewController.view removeFromSuperview];
[self.noContentViewController removeFromParentViewController];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
}
}
这里的问题是第一次
CANoContentViewController
显示,一切正常,并且日志符合预期:2018-06-12 00:58:29.303276+0200 Base[11828:838463] +[CANoContentViewController instantiateController](0x105cc6688) Created CANoContentViewController <CANoContentViewController: 0x7fc350e101f0>
2018-06-12 00:58:29.303517+0200 Base[11828:838463] -[CAProposalsViewController showOrDeleteNoContentIfNeeded](0x7fc35106b200) Set CANoContentViewController <CANoContentViewController: 0x7fc350e101f0>
如您所见,创建的 Controller 在属性中设置正确。
第二次执行此代码,即使是父 View Controller 的新实例,它将实例化
CANoContentViewController
CANoContentViewController
如日志所示正确创建,但未设置为属性:2018-06-12 00:58:31.379708+0200 Base[11828:838463] +[CANoContentViewController instantiateController](0x105cc6688) Created CANoContentViewController <CANoContentViewController: 0x7fc350c8bca0>
2018-06-12 00:58:31.380275+0200 Base[11828:838463] -[CAProposalsViewController showOrDeleteNoContentIfNeeded](0x7fc35181f200) Set CANoContentViewController (null)
所以应用程序崩溃是因为它试图设置
nil
方法中的对象addChildViewController
.任何人都知道为什么第二次这条线不起作用,属性是
nil
?self.noContentViewController = [CANoContentViewController instantiateController];
当我将属性更改为
strong
时,我已经检查过了一切都很好。但我不明白为什么会这样,因为每次 CANoContentViewController
从一个新的父 View Controller 创建 self.noContentViewController
属性应该与前一个不同。
最佳答案
执行后:
self.noContentViewController = [CANoContentViewController instantiateController];
不再有对您创建并分配给弱属性的对象的任何强引用,因此它被释放并且弱属性变为 nil。它第一次起作用的事实只是运气,不能指望。
如果您希望实例存在足够长的时间以在该方法中对其进行处理,请分配给局部变量。
-(void)showOrDeleteNoContentIfNeeded{
if([self.proposals count] <= 0) { // Show No Content VC
CANoContentViewController *controller = [CANoContentViewController instantiateController];
self.noContentViewController = controller;
DLog(@"Set CANoContentViewController %@", self.noContentViewController);
self.noContentViewController.view.frame = self.view.bounds;
[self addChildViewController:self.noContentViewController];
[self.view addSubview:self.noContentViewController.view];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
} else {
[self.noContentViewController.view removeFromSuperview];
[self.noContentViewController removeFromParentViewController];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
}
}
局部变量的使用会在局部变量的作用域内保持强引用。这使引用保持足够长的时间来调用
addChildViewController
这创造了另一个强有力的引用。
关于ios - 将非 nil 对象设置为弱属性第二次返回 nil 但不是第一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50807124/