使用泛型加载带有 nib 的视图控制器

Posted

技术标签:

【中文标题】使用泛型加载带有 nib 的视图控制器【英文标题】:Load viewcontroller with nib using generics 【发布时间】:2016-11-18 12:23:41 【问题描述】:

目前要加载具有相同 nibname 的视图控制器,我使用如下代码

let recommendationVC : RecommendationVC = RecommendationVC(nibName: "RecommendationVC", bundle: nil)

我觉得指定 nibname 是不必要的,因为它与控制器名称相同。所以我决定使用泛型并使用泛型推断类型和笔尖名称

protocol NibIdentifiable 
    static var nibNameIdentifier: String  get 


// MARK: - Indentifies each storyboard from its classname.
extension NibIdentifiable where Self: UIViewController 
    static var nibNameIdentifier: String 
        return String(describing: self)
    

extension UIViewController :NibIdentifiable




extension UIViewController 
    func instantiate<Controller: UIViewController>(_: Controller.Type) -> Controller where Controller: NibIdentifiable 

        guard let controller = Self(nibName:Controller.nibNameIdentifier,bundle:nil) as? Controller else 
            fatalError("Could not dequeue cell with identifier: \(Controller.nibNameIdentifier)")
        

        return controller
    

但在尝试创建 VC 实例时,

 let recommendationVC :RecommendationVC = UIViewController.instantiate()

接收错误 无法推断通用参数“控制器”

这种方法有什么问题?

【问题讨论】:

让推荐VC :RecommendationVC = RecommendationVC.instantiate() 试试这样 @KonstantinKryzhanovsky 我试过了。面临同样的问题 当 nib 名称与类名相同时,您甚至不必指定它。只是做let recommendationVC = RecommendationVC() 应该可以正常工作。 你可以在这里查看我的答案***.com/a/44215068/919545 【参考方案1】:

为 UIViewController 添加扩展

extension UIViewController 
    static func instantiateFromNib() -> Self 
        func instantiateFromNib<T: UIViewController>(_ viewType: T.Type) -> T 
            return T.init(nibName: String(describing: T.self), bundle: nil)
        

        return instantiateFromNib(self)
    

然后就这样使用

让 myViewController = MyViewController.instantiateFromNib()

【讨论】:

谢谢!这对我有用,尽管我没有使用内部功能;我直接打电话给return self.init(nibName: String(describing: self), bundle: nil);【参考方案2】:
class Rec : UIViewController  
    let r : String = "1231231"


protocol NibIdentifiable 
    static var nibNameIdentifier: String  get 


// MARK: - Indentifies each storyboard from its classname.
extension NibIdentifiable where Self: UIViewController 
    static var nibNameIdentifier: String 
        return String(describing: self)
    

    static func instantiate() -> Self 

        guard let controller = Self(nibName:Self.nibNameIdentifier,bundle:nil) as? Self else 
            fatalError("Could not dequeue cell with identifier: \(Self.nibNameIdentifier)")
        

        return controller
    



extension UIViewController : NibIdentifiable 


let x : Rec = Rec.instantiate()

这必须有效。

就我而言,我使用一些 Storyboardable 协议。并从特定的故事板启动控制器。

【讨论】:

以上是关于使用泛型加载带有 nib 的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 .nib 加载视图控制器失败

如何在不使用视图控制器的情况下使用 nib 文件加载视图

使用 nib 中的视图重新加载 UIView 属性

为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib

iOS:加载没有 nib 文件的第二个视图控制器

UIViewController 子类支持NIB加载和非