如果我有一个类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()。
但是假设我有一个名为HomeViewController:BaseViewController的viewController的子类。如果我说let home = HomeViewController.initFromXib(),这确实会成功地返回HomeViewController的一个实例(只要有一个这样命名的Xib ),但作为一个BaseViewController。这没什么错,我要做的就是
let vc = HomeViewController.initFromXib() as? HomeViewController一切都变得很酷。但是,有没有一种方法可以使initFromXib的返回类型成为它所源自的类的“泛型”类型,以便initFromXib始终返回正确类的类型?
发布于 2019-07-05 16:59:08
一种解决方案是具有关联类型的协议扩展,只需在适当的类中采用该协议
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
}
}现在你可以写
let vc = HomeViewController.initFromXib()发布于 2019-07-05 16:59:00
使用泛型
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
}发布于 2019-07-05 17:25:32
请使用下面的解决方案,你甚至不需要使用泛型和TypeCasting。
extension UIViewController {
static func initWithNibName() -> Self {
return self.init(nibName: "\(self)", bundle: nil)
}
}如何在代码中使用?
let homeVC = HomeViewController.initWithNibName()
print(homeVC) // type is HomeViewControllerhttps://stackoverflow.com/questions/56899670
复制相似问题