我正在研究一个我正在重构的遗留应用程序,并且有一种我不理解的奇怪行为。
有一个名为UIViewController
的{{1}},它有一个简单的Nib初始化代码:
CANoContentViewController
然后,如果没有要显示的内容,则其他+ (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>
的父视图控制器的新实例,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
属性应该与前一个属性不同。
答案 0 :(得分:2)
执行后:
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
来创建另一个强引用。
答案 1 :(得分:2)
将属性设置为sample['Time'] = ('0' + sample['Time']) if sample['Time'].str.len() == 3 else sample['Time']
引用应该有效,因为由于仍保留引用指针而未释放引用。
例如set:
strong
而不是:
@property (nonatomic, strong) UIViewController *noContentViewController