self 在 viewController 的方法中总是返回 nil
Posted
技术标签:
【中文标题】self 在 viewController 的方法中总是返回 nil【英文标题】:self always returns nil inside viewController's methods 【发布时间】:2016-01-20 21:04:30 【问题描述】:由于某种原因,我遇到了一个问题,即在 viewController 的代码内部(在调用 viewDidLoad 方法后运行良好),self 总是返回 nil。 (在 ios 9.2.1 的 iPad Air 上运行,以 9.2 为目标构建的应用)。
在初始化代码中,我们有一个普通的初始化器:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
return self;
viewController 像这样被实例化:
myVC * myVC = [[myVC alloc] initWithNibName:nil bundle:nil];
myVC 类和 .xib 文件的名称相同。
有一个属性叫做:
@property (weak, nonatomic) IBOutlet UILabel *ipAddressLabel;
在 myVC 内部的一个方法中,我有一个这样的方法:
- (void) networkPropertiesDidChange:(NSDictionary *)properties
void (^completionBlock)(UIAlertAction *) = ^(UIAlertAction *action)
[self.serialNumberField setEnabled:false];
;
if([properties[@"result" isEqualToString @"error"])
[Utility showBasicAlertControllerWithText:@"Device not registered." completionBlock:completionBlock sender:self];
return;
else if ([properties[@"result"] isEqualToString @"ipChange"])
NSString *newAddy = [[NSString alloc] initWithString:properties[@"ipAddress"]];
self.ipAddressLabel.text = newAddy;
return;
else return;
但是地址标签只是空白。
当我在代码执行时单步执行代码时,在我初始化 newAddy 的那一行,self 不是 nil,并且 ipAddressLabel 不是 nil。但是,当运行时遇到 self.ipAddressLabel.text 时,它会通过 initWithNibName,并为 self 返回 nil!然后 ipAddressLabel 被设置为 nil,然后它在视图上变为空白。
此时 myVC 已经成功加载并显示在屏幕上。所以我不明白为什么 self 在这个方法中为自己返回 nil ......这很奇怪。
如果我删除了对 initWithNibName 方法的覆盖,那么一切都会正常运行。如果我在设置 self=[super...] 之前在 initWithNib 名称的开头检查 if (self != nil),那么视图会在屏幕上绘制 1" 太低并被切断。
只是想了解为什么会这样。谢谢。
【问题讨论】:
只是一些想法:1)添加一个带有 NSLog 的 dealloc 方法,看看它是否被调用(并且由于某种原因这个对象没有被保留) - 2)为您的 ipAddressLabel 添加您自己的客户设置器,记录它何时设置为某个值以及值(以查看它是否为零)。在你的方法中添加断言(或 NSAsserts)来测试 ipAddressLabel 是否为 nil。 无法添加 dealloc,我使用的是 ARC。我已经尝试添加自定义设置器,但无法在 nil 对象上调用方法。我添加了断言并且 ipAddressLabel 不是 nil,直到我调用self.ipAddressLabel.text = newAddy;
...
Dealloc 仍在 arc 下发送
【参考方案1】:
问题出在这里:
void (^completionBlock)(UIAlertAction *) = ^(UIAlertAction *action)
[self.serialNumberField setEnabled:false];
;
需要是weakSelf……
__weak typeof(self) weakSelf = self;
void (^completionBlock)(UIAlertAction *) = ^(UIAlertAction *action)
[weakSelf.paxSerialNumberField setEnabled:false];
;
别问我为什么,我的大脑爆炸了。
【讨论】:
以上是关于self 在 viewController 的方法中总是返回 nil的主要内容,如果未能解决你的问题,请参考以下文章
iOS Swift 使用 Segue 在 viewController 之间传递变量
使用情节提要 xcode 6 在 viewController 中调整内容
self.presentingViewController presentViewController 不工作
覆盖单独的SecondaryViewControllerForSplitViewController:用于单点触控中的特定UIViewController