第二次将非 nil 对象设置为弱 属性 returns nil 但不是第一次
Setting a non-nil object to a weak property returns nil second time but not first one
我正在开发一个我正在重构的遗留应用程序,并且有一个我不理解的奇怪行为。
有一个名为 CANoContentViewController
的 UIViewController
,它有一个来自 Nib 的简单初始化代码:
+ (CANoContentViewController *)instantiateController {
CANoContentViewController *vc = [[CANoContentViewController alloc] initWithNibName:@"CANoContentViewController" bundle:[NSBundle mainBundle]];
DLog(@"Created CANoContentViewController %@", vc);
return vc;
}
然后,otherUIViewController
没有内容显示就显示。这是代码:
@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>
如您所见,创建的控制器在属性中设置正确。
第二次执行此代码,即使是将实例化 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)
所以应用程序崩溃是因为它试图在方法 addChildViewController
中设置一个 nil
对象。
任何人都知道为什么这条线第二次不起作用并且 属性 是 nil
?
self.noContentViewController = [CANoContentViewController instantiateController];
我检查过当我将 属性 更改为 strong
时一切正常。但我不明白为什么会这样,因为每次从新的父视图控制器创建 CANoContentViewController
时,self.noContentViewController
属性 应该与前一个不同。
执行后:
self.noContentViewController = [CANoContentViewController instantiateController];
不再有对您创建并分配给弱 属性 的对象的强引用,因此它被释放并且弱 属性 变为零。第一次成功只是运气,不能指望。
如果您希望实例存活足够长的时间以在该方法中对其进行处理,请分配给局部变量。
-(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
,从而创建另一个强引用。
将您的 属性 设置为 strong
引用应该可行,因为该引用未被释放,因为它仍然保留着一个引用指针。
例如设置:
@property (nonatomic, strong) UIViewController *noContentViewController
而不是:
@property (nonatomic, weak) UIViewController *noContentViewController
我正在开发一个我正在重构的遗留应用程序,并且有一个我不理解的奇怪行为。
有一个名为 CANoContentViewController
的 UIViewController
,它有一个来自 Nib 的简单初始化代码:
+ (CANoContentViewController *)instantiateController {
CANoContentViewController *vc = [[CANoContentViewController alloc] initWithNibName:@"CANoContentViewController" bundle:[NSBundle mainBundle]];
DLog(@"Created CANoContentViewController %@", vc);
return vc;
}
然后,otherUIViewController
没有内容显示就显示。这是代码:
@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>
如您所见,创建的控制器在属性中设置正确。
第二次执行此代码,即使是将实例化 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)
所以应用程序崩溃是因为它试图在方法 addChildViewController
中设置一个 nil
对象。
任何人都知道为什么这条线第二次不起作用并且 属性 是 nil
?
self.noContentViewController = [CANoContentViewController instantiateController];
我检查过当我将 属性 更改为 strong
时一切正常。但我不明白为什么会这样,因为每次从新的父视图控制器创建 CANoContentViewController
时,self.noContentViewController
属性 应该与前一个不同。
执行后:
self.noContentViewController = [CANoContentViewController instantiateController];
不再有对您创建并分配给弱 属性 的对象的强引用,因此它被释放并且弱 属性 变为零。第一次成功只是运气,不能指望。
如果您希望实例存活足够长的时间以在该方法中对其进行处理,请分配给局部变量。
-(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
,从而创建另一个强引用。
将您的 属性 设置为 strong
引用应该可行,因为该引用未被释放,因为它仍然保留着一个引用指针。
例如设置:
@property (nonatomic, strong) UIViewController *noContentViewController
而不是:
@property (nonatomic, weak) UIViewController *noContentViewController