我在UIView
上有一个扩展名,用于加载某个类型和名称的笔尖:
extension UIView {
class func fromNib<T : UIView>() -> T? {
guard let nib = Bundle(for: T.self).loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0]
else {
return nil
}
return nib as? T
}
}
现在在我的Hint
类(UIView
的子类)中,我使用上面的扩展名:
if let view = Hint.fromNib(){
self.addSubview(view)
view.frame = self.bounds
}
这不起作用,因为T.self
的结果始终是UIView,即使提示是调用fromNib
方法的类。如果我尝试对这样的类进行硬编码:
Bundle(for: Hint.self).loadNibNamed(String(describing: Hint.self), owner: nil, options: nil)
然后一切正常。如何获取实际调用fromNib()
方法的类的类型名称?
这是我的提示课:
class Hint:UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if let view = UIView.fromNib(){
self.addSubview(view)
view.frame = self.bounds
}
}
override init(frame: CGRect) {
super.init(frame: frame)
if let view = UIView.fromNib(){
self.addSubview(view)
view.frame = self.bounds
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
if let view = UIView.fromNib(){
self.addSubview(view)
view.frame = self.bounds
}
}
}
所以一切都很简单。一个nib文件只有一个标签和一个图像视图,但我想这与当前问题几乎无关。
答案 0 :(得分:1)
我用完全相同的方法遇到了完全相同的问题,甚至将其命名为相同。我无法使用当前的类类型,因为编译器假定它是UIView
而不是它的子类。
Hint.fromNib()
最终与UIView.fromNib()
完全相同,因为T
并不依赖于被调用的类,所以会发生什么事情,所以T
被推断为UIView
。您需要做的是通过指定您希望获得的视图类型来帮助编译器推断出正确的类型。
let hint: Hint? = UIView.fromNib()
我想补充一点,当您正确使用guard
时,first
比[0]
更安全,所以我会将您的方法更改为:
let bundle = Bundle(for: T.self)
let nib = bundle.loadNibNamed(String(describing: T.self), owner: nil, options: nil)
guard let view = nib?.first as? T else {
return nil
}
return view
答案 1 :(得分:1)
您想知道调用类fromNib()
的类型,即类方法中的self
:
extension UIView {
class func fromNib<T : UIView>() -> T? {
guard
let nibs = Bundle(for: self).loadNibNamed(String(describing: self), owner: nil, options: nil),
let nib = nibs.first
else {
return nil
}
return nib as? T
}
}
以下内容:
if let viewFromXib = MyXib.fromNib(){
view.addSubview(viewFromXib)
viewFromXib.frame = CGRect(origin: CGPoint.zero, size: CGSize(width: 30, height: 30))
print(viewFromXib)
}
工作和打印:
<TESTS.MyXib: 0x7f9531408aa0; frame = (0 0; 30 30); autoresize = W+H; layer = <CALayer: 0x60000002b8e0>>
我真的不明白如何推断返回类型T
。
更新
我正在深入研究如何推断返回类型T
,答案是:它没有。
此:
class func fromNib() -> UIView? {
guard
let nibs = Bundle(for: self).loadNibNamed(String(describing: self), owner: nil, options: nil),
let nib = nibs.first
else {
return nil
}
return nib as? UIView
}
等同。
所以,即使这个答案正在解决问题,也没有回答这个问题。