根据类更改函数的返回类型

时间:2019-07-05 08:48:29

标签: ios swift

如果我有一个类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总是返回正确的类的类型?

3 个答案:

答案 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