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

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?
    }
}

方法的目的是确定这个视图是从代码创建的,还是从相应的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
}

它使用一个技巧来确定视图是否是从代码创建的,因为在这种情况下,它正好包含两个子视图,这两个子视图都实现了isRawView()协议。
当从代码实例化一个UILayoutSupport子类时,这很好地工作。但是,如果视图是作为情节提要中的视图控制器的一部分创建的(并且可能对于视图控制器和从XIB文件加载的视图也会发生同样的情况),那么它就不起作用。
长话短说来解释我的问题的原因:是否有办法让NibView知道它是否是从XIB文件加载的,以及该文件的名称?或者,否则,另一种实现UIView方法的方法,它应该:
如果视图已从关联的XIB文件(其名称是类名)反序列化,则返回isRawView()
否则返回

最佳答案

使用提供的init函数。
init(frame:​)->来自代码
来自nib的
示例代码:

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")

你应该可以用它,也许稍加调整,得到你所需要的。

关于ios - 确定`UIView`是从XIB加载还是从代码实例化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43186387/

10-10 22:24