self 在 vi​​ewController 的方法中总是返回 nil

Posted

技术标签:

【中文标题】self 在 vi​​ewController 的方法中总是返回 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 在 vi​​ewController 的方法中总是返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift 使用 Segue 在 vi​​ewController 之间传递变量

使用情节提要 xcode 6 在 vi​​ewController 中调整内容

self.presentingViewController presentViewController 不工作

表的头视图下拉放大效果

覆盖单独的SecondaryViewControllerForSplitViewController:用于单点触控中的特定UIViewController

将 Subview 传递给子类 UIView