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

标签 ios objective-c properties weak-references

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

有一个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/

相关文章:

html - CSS 问题 : IE 6+ not display 'cursor' correctly - ninja help needed

ios - Restkit 映射 - 使用嵌入对象/关系作为标识属性

ios - 使用捆绑资源进行测试的最简单方法

ios - 使用字符串作为名称来设置属性值

ios - iOS 模拟器中的 AVAudioPlayer 不播放声音

objective-c - 在 Cocoa 中创建动画 GIF - 定义帧类型

iphone - Sqlite 数据检索问题

Mac OS X 上的 Java System.getProperty ("user.dir")

java - 如果在命令行参数中指定,则覆盖属性文件值

ios - 取消完成处理程序 (iOS)