我使用以下代码强制 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()
方法的目的是确定此 View 是从代码创建的,还是从相应的 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
}
它使用一个技巧来确定 View 是否是从代码创建的,因为在这种情况下它恰好包含 2 个 subview ,它们都实现了 UILayoutSupport
协议(protocol)。
当 NibView
子类从代码实例化时,这会很好地工作。但是,如果 View 是作为 Storyboard 中 View Controller 的一部分创建的,则它不起作用(对于 View Controller 和从 XIB 文件加载的 View ,可能会发生同样的情况)。
长篇大论来解释我的问题的原因:UIView
是否有办法知道它是否是从 XIB 文件加载的,可能还有该文件的名称? 或者,另一种实现 isRawView()
方法的方法,应该:
- 如果 View 已从关联的 XIB 文件(其名称是类名)反序列化,则返回
false
- 返回
true
否则
最佳答案
利用提供的 init
函数。
-
init(frame:)
-> 来自代码 -
init(coder:)
-> 来自 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/