如果我有一个类BaseViewController:UIViewController
,并且想要一种从Xib实例化此viewController的方法,则可以这样做:
class func initFromXib()->BaseViewController?{
let nibName = String(NSStringFromClass(self).split(separator: ".").last ?? "")
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: nil, options: nil).first as? BaseViewController
}
每当我需要从xib初始化ViewController时,我都可以说let vc = BaseViewController.initFromXib()
。
但是,假设我有一个此viewController的子类,名为HomeViewController:BaseViewController
。
如果我说let home = HomeViewController.initFromXib()
,这确实会成功返回HomeViewController
的实例(只要有一个名为Xib的Xib),但是会返回BaseViewController
。没问题,我要做的就是
let vc = HomeViewController.initFromXib() as? HomeViewController
一切都很酷。但是,是否有一种方法可以使initFromXib
的返回类型成为其源自的类的“泛型”类型,以便initFromXib
总是返回正确的类的类型?
答案 0 :(得分:1)
使用泛型
@EnableAspectJAutoProxy(proxyTargetClass = true)
答案 1 :(得分:1)
解决方案是具有相关类型的协议扩展,只需在适当的类中采用协议即可
class func initFromXib<T: BaseViewController>()-> T?{
let nibName = String(NSStringFromClass(self).split(separator: ".").last ?? "")
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: nil, options: nil).first as? T
}
现在您可以写
protocol XibInitializable {
associatedtype ControllerType : UIViewController = Self
static func initFromXib() -> ControllerType?
}
extension XibInitializable where Self : UIViewController {
static func initFromXib() -> ControllerType? {
let nibName = String(describing: Self.self)
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiate(withOwner: nil, options: nil).first as? ControllerType
}
}
答案 2 :(得分:0)
请使用以下解决方案,甚至不需要使用泛型和TypeCasting。
extension UIViewController {
static func initWithNibName() -> Self {
return self.init(nibName: "\(self)", bundle: nil)
}
}
如何在代码中使用?
let homeVC = HomeViewController.initWithNibName()
print(homeVC) // type is HomeViewController