1

Consider this pattern

extension UIViewController
{
    class func make(sb: String, id: String) -> Self
    {
        return helper(sb:sb, id:id)
    }

    private class func helper<T>(sb: String,id: String) -> T
    {
        let s = UIStoryboard(name: storyboardName, bundle: nil)
        let c = s.instantiateViewControllerWithIdentifier(id) as! T
        return c
    }
}

that works fine, so

let s = SomeViewControllerClass.make( ... )

does in fact return the subclass "SomeViewControllerClass". (Not just a UIViewController.)

That's all fine BUT,

say in make you want to do some setup:

    class func make(sb: String, id: String) -> Self
    {
        let h = helper(sb:sb, id:id)
        // some setup, m.view = blah etc
        return h
    }

in fact it appears you cannot do that.

You can only

        return helper(sb:sb, id:id)

you cannot

        let h = helper(sb:sb, id:id)
        return h

is there a solution?

Community
  • 1
  • 1
Fattie
  • 30,632
  • 54
  • 336
  • 607
  • 2
    Well, that is the "trick" in the referenced pattern. In `return helper(sb:sb, id:id)` the generic placeholder type `T` is inferred from `Self`. – You can always move additional setup into the helper method. – Martin R Feb 10 '17 at 14:31
  • Or add a `T.Type` parameter to `helper`, such as shown in http://stackoverflow.com/q/37240091/2976878. Then just pass in `self` for that parameter and `T` will be inferred to be `Self`. – Hamish Feb 10 '17 at 14:40
  • I see what you mean @MartinR, thanks ... – Fattie Feb 10 '17 at 14:45
  • @Hamish - excellent idea >thumbs up emoji – Fattie Feb 10 '17 at 14:45

1 Answers1

2

Of course there is a solution. That's exactly what the helper function is doing.

Why don't you put the code into helper?

To invoke helper, which is a generic type, you have to specify the type somehow, e.g.

let h: Self = helper(...)

or

let h = helper(...) as Self

but neither of those expressions would actually accept Self. Therefore, you need to infer the type from the return value -> Self. That's why return is the only thing that works.

Also note that you can use a second helper function.

class func make(sb: String, id: String) -> Self {
    let instance = helper2(sb: sb, id: id)        
    return instance
}

class func helper2(sb: String, id: String) -> Self {
    return helper(sb:sb, id:id)
}
Sulthan
  • 118,286
  • 20
  • 194
  • 245
  • @JoeBlow It helps, see the example. `helper2` infers the generic type of `helper` and `make` can then use the type directly. – Sulthan Feb 10 '17 at 14:55
  • quite right guys, of course you just put setup code it in the "helper" function. good one. – Fattie Feb 10 '17 at 15:27
  • how are you @sulthan - say, there's https://stackoverflow.com/questions/44187881 a question looking for a kind of canonical iOS answer! cheers.. – Fattie Jun 03 '17 at 18:09