ChikabuZ ChikabuZ - 3 months ago 66
Swift Question

Return instancetype in Swift

I'm trying to make this extension:

extension UIViewController
{
class func initialize(storyboardName: String, storyboardId: String) -> Self
{
let storyboad = UIStoryboard(name: storyboardName, bundle: nil)
let controller = storyboad.instantiateViewControllerWithIdentifier(storyboardId) as! Self

return controller
}
}


But I get compile error:


error: cannot convert return expression of type 'UIViewController' to
return type 'Self'


Is it possible? Also I want to make it as
init(storyboardName: String, storyboardId: String)


Update:

Thanks to Martin R answer the final extension looks like this:

extension UIViewController
{
class func instantiateFromStoryboard(name: String = "Main") -> Self
{
return instantiateFromStoryboardHelper(name)
}

private class func instantiateFromStoryboardHelper<T>(name: String) -> T
{
let storyboard = UIStoryboard(name: name, bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier(String(self)) as! T
return controller
}
}


Usage:

let myViewController = MyViewController.instantiateFromStoryboard()

Answer

Similar as in Using 'self' in class extension functions in Swift, you can define a generic helper method which infers the type of self from the calling context:

extension UIViewController
{
    class func instantiateFromStoryboard(storyboardName: String, storyboardId: String) -> Self
    {
        return instantiateFromStoryboardHelper(storyboardName, storyboardId: storyboardId)
    }

    private class func instantiateFromStoryboardHelper<T>(storyboardName: String, storyboardId: String) -> T
    {
        let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
        let controller = storyboard.instantiateViewControllerWithIdentifier(storyboardId) as! T
        return controller
    }
}

Then

let vc = MyViewController.instantiateFromStoryboard("name", storyboardId: "id")

compiles, and the type is inferred as MyViewController.

Comments