Swift 中的 UIView 子类:IBOutlet 在展开时发现为零

Posted

技术标签:

【中文标题】Swift 中的 UIView 子类:IBOutlet 在展开时发现为零【英文标题】:UIView subclass in Swift: IBOutlet is found nil while unwrapping 【发布时间】:2016-01-09 23:16:56 【问题描述】:

我正在尝试通过子类化UIView 在 Swift 中创建自定义视图,并且我有一个名为 MyViewPanel.xib 的视图板,它的类分配给了 MyCustomView。实现如下:

import UIKit
@IBDesignable
class MyCustomView: UIView 
 @IBOutlet weak var title: UILabel!

 var question: Question 
     didSet 
        print("did set question, title is: \(question.title)")
     
 

 override init(frame: CGRect) 
        super.init(frame: frame)
    


required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
    

override func drawRect(rect: CGRect) 
        let height = rect.height
        let width = rect.width
        let color: UIColor = UIColor.whiteColor()

        let drect = CGRect(x: (width * 0.25), y: (height * 0.25), width: (width * 0.5),height: (height * 0.5))
        let bpath: UIBezierPath = UIBezierPath(rect: drect)
        color.set()
        bpath.stroke()
    

override func awakeFromNib() 
        super.awakeFromNib()
        print("awake from nib!")
        self.title.text = "Test title" // error: found nil while unwrapping an Optional Value 
    

在运行过程中,遇到如下错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

由于awakeFromNib()UIView 中的第一个生命周期事件,我不明白为什么title UILabel 在这种情况下为零。

编辑:

要使用这个自定义视图,我只需在我的故事板上绘制一个UIView 矩形并将其类分配给MyCustomView。在我的故事板ViewControllerviewDidLoad() 方法中,我在自定义视图上设置了问题:

override func viewDidLoad() 
   // myCustomView is an IBOutlet in the view controller
   myCustomView.question = question

【问题讨论】:

如何创建视图实例? 我只是在我的故事板上画了一个UIView 矩形并将其类分配给MyCustomView。这是错的吗?谢谢 那么你找到这个问题的答案了吗? @TonyGW,这是正确的。你有没有最终找到一个不涉及 UIViewController 的问题的解决方案?我想做一个通用的 UIView 对视图控制器没有任何意见。很好的问题。如果可以的话,我会再次投票。 【参考方案1】:

代码部分看起来不错,但这表明在接口构建器中未正确连接插座。在 interface builder 的 outlets 部分中,您可以看到标题 outlet 已连接并且不显示指示错误的感叹号。此外,代码中的 IBOutlet 行旁边应该有一个实心圆圈,表示插座连接正确,并且接口生成器正确分配了类。

【讨论】:

是的,我仔细检查了 IBOutlets 的连接,圆圈被填满,连接检查器也显示了连接。谢谢【参考方案2】:

我想出了如何在我编写的 UIView 子类的便利初始化程序中为 UILabel 设置文本:

@IBOutlet weak var messageLabel: UILabel!

init?(frame: CGRect, message: String) 
    super.init(frame: frame)

    guard let view = NSBundle.mainBundle().loadNibNamed("MyViewSubclass", owner: self, options: nil).first as? MyViewSubclass else 
        return nil
    

    // Without the following line, my view was always 600 x 600
    view.frame = frame

    self.addSubview(view)

    guard let messageLabel = view.messageLabel else 
        return
    

    messageLabel.text = message

【讨论】:

以上是关于Swift 中的 UIView 子类:IBOutlet 在展开时发现为零的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖子类的 swift 协议函数(例如 UIView 中的 UILabel)

UIView 子类在 Swift 中设置自己的高度 + UIViewController 中的约束 + 情节提要

如何将 UIView XIB“导入”到 UIViewController XIB?

无法访问 Swift 子类中的 oc 类别方法

将 UIView 作为 SubView 添加到自定义类、UIView 的子类、Swift

UIView 子类的 Swift 通用方法