【问题标题】:IBOutlet properties nil after custom view loaded from xib从 xib 加载自定义视图后 IBOutlet 属性为零
【发布时间】:2015-04-07 17:08:05
【问题描述】:

IBOutlets 发生了一些奇怪的事情。

在代码中我尝试访问此属性,但它们是nil。代码:

class CustomKeyboard: UIView {

    @IBOutlet var aButt: UIButton!
    @IBOutlet var oButt: UIButton!

    class func keyboard() -> UIView {
        let nib = UINib(nibName: "CustomKeyboard", bundle: nil)
        return nib.instantiateWithOwner(self, options: nil).first as UIView
    }

    override init() {
        super.init()
        commonInit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    // MARK: - Private
    private func commonInit() {
        println(aButt)
        // aButt is nil

        aButt = self.viewWithTag(1) as UIButton
        println(aButt)
        // aButt is not nil
    }
}

【问题讨论】:

  • 除了commonInit,你还在哪里访问它们?
  • @AshrafTawfeeq 现在无处可去。我无法正常启动此类。清洁项目也无济于事
  • 在初始化时尚未设置 Outlets,因为视图尚未加载。您的第二个日志有效,因为访问视图会导致它被加载。
  • @rdelmar 视图已经加载,我可以和他一起工作。但似乎插座没有连接。如果我在初始化后立即从ViewController 直接调用commonInitaButt 不为零。
  • 我花了几个小时试图解决类似的问题。在我明白我将插座连接到错误的视图之前:)

标签: ios swift uiview nib


【解决方案1】:

您是如何从控制器启动视图的?像这样:

var view = CustomKeyboard.keyboard()
self.view.addSubview(view)

【讨论】:

  • 像这样:textField.inputView = CustomKeyboard.keyboard() 没关系。
  • 您没有发布您的代码,如果您使用var view = CustomKeyboard();,那么结果将与您的情况一样:您的网点越来越为零。这就是我问的原因。
【解决方案2】:

这是意料之中的,因为在调用初始化程序时未分配 IBOutlet(s)。您不需要 commonInit,只需覆盖 awakeFromNib,如下所示:

override func awakeFromNib() {
    super.awakeFromNib()

    print(aButt)
}

【讨论】:

  • 已经有了...仍然收到错误。此外,我的网点显示为已连接,该类在 xib 中匹配。甚至使引用类型变强,仍然没有。
  • @ScottyBlades 你发现了吗?
  • @MarceloRibeiro,不……我没有。但我可以告诉你从awakefromnib 而不是init(frame: CGRect) 调用时为零
  • @MarceloRibeiro,你必须这样做:override func awakeAfter(using aDecoder: NSCoder) -> Any? { guard subviews.isEmpty else { return self } return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first }
【解决方案3】:

您的笔尖可能未连接。我的解决方案很简单。在你项目的某个地方(我创建了一个名为 UIViewExtension.swift 的类),使用这个方便的 connectNibUI 方法添加 UIView 的扩展。

extension UIView {
    func connectNibUI() {
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: nil).instantiate(withOwner: self, options: nil)
        let nibView = nib.first as! UIView
        nibView.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(nibView)
        //I am using SnapKit cocoapod for this method, to update constraints.  You can use NSLayoutConstraints if you prefer.
        nibView.snp.makeConstraints { (make) -> Void in
            make.edges.equalTo(self)
        }
    }
}

现在您可以在任何视图上调用此方法,在您的 init 方法中执行以下操作:

override init(frame: CGRect) {
    super.init(frame: frame)
    connectNibUI()
}

【讨论】:

  • 还要确保您的视图是通过“文件所有者”连接的。
【解决方案4】:

假设您尝试了连接 IBOutlets 的标准故障排除步骤,请尝试以下操作:

显然,在某些运行时情况下,您需要禁用从 nib 唤醒。

  override func awakeAfter(using aDecoder: NSCoder) -> Any? {
      guard subviews.isEmpty else { return self }
      return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
  }

【讨论】:

    【解决方案5】:

    在@ScottyBlades 的基础上,我创建了这个子类:

    class UIViewXib: UIView {
        // I'm finding this necessary when I name a Xib-based UIView in IB. Otherwise, the IBOutlets are not loaded in awakeFromNib.
        override func awakeAfter(using aDecoder: NSCoder) -> Any? {
            guard subviews.isEmpty else { return self }
            return Bundle.main.loadNibNamed(typeName(self), owner: nil, options: nil)?.first
        }
    }
    
    func typeName(_ some: Any) -> String {
        return (some is Any.Type) ? "\(some)" : "\(type(of: some))"
    }
    

    【讨论】:

    • 虽然这种方法存在一个问题。由于视图重新初始化,所有通过 xib 完成的设置都将丢失。但至少子视图的出口是完整的。
    【解决方案6】:

    您可能没有提到 xib 的 FileOwner。 在文件所有者而不是在视图身份检查器中提及其类。

    【讨论】:

      猜你喜欢
      • 2018-12-06
      • 2019-10-01
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      • 1970-01-01
      相关资源
      最近更新 更多