繁体   English   中英

确定是从UIB加载`UIView`还是从代码实例化

[英]Determine if `UIView` is loaded from XIB or instantiated from code

我使用以下代码强制UIView的子类从名称为实际类名的XIB文件加载:

class NibView : UIView {
    override func awakeAfter(using aDecoder: NSCoder) -> Any? {
        guard isRawView() else { return self }
        for view in self.subviews {
            view.removeFromSuperview()
        }

        let view = instanceFromNib()
        return view
    }

    func isRawView() -> Bool {
        // What here?
    }
}

isRawView()方法的目的是确定此视图是从代码创建的,还是从相应的XIB文件加载的。 到目前为止我使用的实现是:

func isRawView() -> Bool {
    // A subview created by code (as opposed to  being deserialized from a nib)
    // has 2 subviews, both implementing the `UILayerSupport` protocol
    return
        self.subviews.count == 2 &&
        self.subviews.flatMap(
            { $0.conforms(to: UILayoutSupport.self) ? $0 : nil }).count == 2
}

它使用技巧来确定视图是否是从代码创建的,因为在这种情况下它只包含2 UILayoutSupport视图,两者都实现了UILayoutSupport协议。

当从代码实例化NibView子类时,这很好用。 但是,如果视图是作为故事板中视图控制器的一部分创建的,则它不起作用 (对于视图控制器和从XIB文件加载的视图,可能会发生相同的情况)。

很长一段时间来解释我的问题的原因: 有没有办法让UIView知道它是从XIB文件加载,还是可能是该文件的名称? 或者,否则,实现isRawView()方法的另一种方法,它应该:

  • 如果视图已从关联的XIB文件(其名称是类名)反序列化,则返回false
  • 否则返回true

利用提供的init函数。

示例代码:

override init(frame: CGRect) {
    super.init(frame: frame)
    print("From code")
}

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    print("From nib")
}

我可以像这样打印出类名:

print(NSStringFromClass(type(of: self)).components(separatedBy: ".").last ?? "Couldn't get it")

你应该可以使用它,也许稍作调整,以获得你需要的东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM