Cloud9999Strife
Cloud9999Strife

Reputation: 3202

Swift - Generic Functions

The Goal

I want to call the instantiateViewControllerWithIdentifier method on a Storyboard to get a view controller. But I want to do it with generics for code reuse and simplicity.

The Non-Compiling Code

let viewController = StoryboardHelper.viewControllerFromStoryboard<ChooseProviderViewController>()

class func viewControllerFromStoryboard<T>() -> T {
        let storyboard = mainStoryboard()
        let viewController = storyboard.instantiateViewControllerWithIdentifier(resolveViewController(T)) as T

        return viewController
    }

private class func resolveViewController<T>() -> String {
        if T is ChooseProviderViewController {
            return chooseProviderViewControllerIdentifier;
        }

        return ""
    }

Now, the above code is what I have at the moment, and how I would like the API to be. It would be nice to say "StoryboardHelper, here is the type of the view controller I want, go get the view controller instance for me".

So, in the end, I would like some way to do this:

let instanceOfXViewController = StoryboardHelper.viewControllerFromStoryboard<XViewController>()

let instanceOfYViewController = StoryboardHelper.viewControllerFromStoryboard<YViewController>()

Upvotes: 0

Views: 494

Answers (1)

Alex
Alex

Reputation: 541

I have a answer for you but it will only work with Swift 1.2 (+), in 1.1 it will return a intance of the wrong (super) type. I changed it to a more general situation/naming but it is effectly the same problem. First since you only want to manage UIViewControllers you should restrict T. Like <T:UIViewController> . Secondly you should/can pass the Type as an argument and create an instance of it.

import Foundation

class Helper {
    class func instanceFromT<T:R>(T.Type) -> T {
        return T.self()
    }
}

class R {
    required init () {

    }
    func me() -> String {
        return "me is R"
    }
}

class B : R {
    override func me() -> String {
        return "me is B"
    }
}

class A : R {
    override func me() -> String {
        return "me is A"
    }
}

let my = Helper.instanceFromT(A.self)

println(my.me()) // "me is A"

Upvotes: 1

Related Questions