简体   繁体   English

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

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

I use the following code to force a subclass of UIView to load from a XIB file whose name is the actual class name: 我使用以下代码强制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?
    }
}

The purpose of the isRawView() method is to determine whether this view has been created from code, or it's been loaded from the corresponding XIB file. isRawView()方法的目的是确定此视图是从代码创建的,还是从相应的XIB文件加载的。 The implementation I've used so far is: 到目前为止我使用的实现是:

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
}

which uses a trick to determine if the view is created from code, because in such cases it contains exactly 2 subviews, both implementing the UILayoutSupport protocol. 它使用技巧来确定视图是否是从代码创建的,因为在这种情况下它只包含2 UILayoutSupport视图,两者都实现了UILayoutSupport协议。

This works nicely when a NibView subclass is instantiated from code. 当从代码实例化NibView子类时,这很好用。 However it doesn't work if the view is created as part of a view controller in a storyboard (and presumably the same happens for view controllers and views loaded from XIB files). 但是,如果视图是作为故事板中视图控制器的一部分创建的,则它不起作用 (对于视图控制器和从XIB文件加载的视图,可能会发生相同的情况)。

Long story to explain the reason of my question: is there a way for a UIView to know whether it's been loaded from a XIB file, and possibly the name of that file? 很长一段时间来解释我的问题的原因: 有没有办法让UIView知道它是从XIB文件加载,还是可能是该文件的名称? Or, otherwise, an alternative way of implementing the isRawView() method, which should: 或者,否则,实现isRawView()方法的另一种方法,它应该:

  • return false if the view has been deserialized from an associated XIB file (whose name is the class name) 如果视图已从关联的XIB文件(其名称是类名)反序列化,则返回false
  • return true otherwise 否则返回true

Make use of the provided init functions. 利用提供的init函数。

Example code: 示例代码:

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

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

I can print out the class name like this: 我可以像这样打印出类名:

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

You should be able to use that, maybe with some slight adjustments, to get what you need. 你应该可以使用它,也许稍作调整,以获得你需要的东西。

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

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