将非零对象设置为弱属性将返回nil第二次但不是第一次

时间:2018-06-11 22:57:12

标签: ios objective-c properties weak-references

我正在研究一个我正在重构的遗留应用程序,并且有一种我不理解的奇怪行为。

有一个名为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属性应该与前一个属性不同。

2 个答案:

答案 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