Consider a base UIViewController class...
class Rooms: UIViewController {
class func instantiate()->Rooms {
}
static func make()->Rooms {
let emplacedAndSetup = self.instantiate()
// various kodes here
// very likely put s.view somewhere
return emplacedAndSetup
}
sundryOtherFunctionality()
}
(Note the self.
before instantiate()
which seems to be necessary to get "that" instantiator.)
Each subclass knows its own storyboard ID to how use to instantiateViewController
:
class Dining: Rooms {
override class func instantiate()->Dining { // returns a "Dining"
let d = stbd.instantiateViewController(
withIdentifier: "Some Specific Scene") as! Dining
return d
}
}
class Bath: Rooms {
override class func instantiate()->Bath { // returns a "Bath"
let b = stbd.instantiateViewController(
withIdentifier: "Some Other Scene") as! Bath
return b
}
}
You can do this,
let d = Dining.make()
let r = Bath.make()
The only minor problem is, it returns the base class. BUT SEE BELOW. So in practice you have to
let d = Dining.make() as! Dining
let r = Bath.make() as! Bath
Is there a way to modify the static make
so that indeed Dining.make()
would return a Dining
and Bath.make()
would return a Bath
?
( @Hamish has pointed out that one could use an init
and Self
pattern, Method that returns object of type which was called from However, I think that's not possible due to the instantiateViewController
. )
So. Say you have code like
let d = Dining.make(blah blah)
in fact. At run time, d does become a "Dining", not a "Room"
that's fantastic.
But. If you do this in the IDE
let d:Dining = Dining.make(blah blah)
it fails - it thinks d is going to be a Room, not a Dining.
So all your code has to look like this:
let d = Dining.make(blah blah) as! Dining
which sucks. How to fix?
Note just TBC the solution is to make the static a generic, rather as in MartinR's answer here https://stackoverflow.com/a/33200426/294884 Example code in answer below.
You can do something like this.
Next you put the
make()
method into a protocol extension.Now you can write
And this code will work
I don't like to provide my own answer, but the solution is ..
So the problem is, at editor time
"doesn't work", you have to do this
(It DOES work at compile time, d becomes a Dining: it doesn't "work" at editor time.)
So the solution is
becomes
So that's it.
Note - it's entirely possible
AppzForLife
's solution works and/or is better as a general purpose "UIViewController auto-instantiator", but this is the answer to the question per se.