Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load viewcontroller with nib using generics

Currently to load viewcontroller with same nibname I use code as follows

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

I feel specifying nibname is unncessary as it is same as controller name. So i decided to use generics and infer type and nib name using generics

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
    }
}

But on trying to create a VC instance,

 let recommendationVC :RecommendationVC = UIViewController.instantiate()

receiving error Generic parameter 'Controller' could not be inferred

What is wrong in this approach?

like image 579
Deekshith Bellare Avatar asked Aug 08 '26 22:08

Deekshith Bellare


2 Answers

Add the extension for 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)
    }
}

and then use just like that

let myViewController = MyViewController.instantiateFromNib()

like image 111
invoodoo Avatar answered Aug 11 '26 12:08

invoodoo


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()

This must works.

In my case i use some Storyboardable protocol. and initiate Controller from specific storyboard.

like image 25
Konstantin Kryzhanovsky Avatar answered Aug 11 '26 12:08

Konstantin Kryzhanovsky



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!