Рассмотрим базовый класс UIViewController...
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()
}
(Обратите внимание на self.
перед instantiate()
, что кажется необходимым для получения "этого" экземпляра.)
Каждый подкласс знает свой собственный идентификатор раскадровки, как использовать его для 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
}
}
Ты можешь это сделать,
let d = Dining.make()
let r = Bath.make()
Единственная небольшая проблема в том, что он возвращает базовый класс. НО СМОТРИТЕ НИЖЕ. Так что на практике вы должны
let d = Dining.make() as! Dining
let r = Bath.make() as! Bath
Есть ли способ изменить статический make
так, чтобы Dining.make()
действительно возвращал Dining
, а Bath.make()
возвращал Bath
?
( @Hamish указал, что можно использовать шаблон init
и Self
, метод, который возвращает объект типа, который был вызван из Однако я думаю, что это невозможно из-за instantiateViewController
. )
Так. Скажем, у вас есть код вроде
let d = Dining.make(blah blah)
по факту. Во время выполнения d становится "столовой", а не "комнатой"
это чудесно.
Но. Если вы сделаете это в IDE
let d:Dining = Dining.make(blah blah)
он терпит неудачу - он думает, что d будет Room, не Dining.
Итак, весь ваш код должен выглядеть так:
let d = Dining.make(blah blah) as! Dining
что отстой. Как исправить?
Обратите внимание, просто TBC решение состоит в том, чтобы сделать статику универсальной, как в ответе MartinR здесь https://stackoverflow.com/a/33200426/294884 Пример кода в ответе ниже.
required
вместо статического методаinstantiate()
(а затем переопределить этот инициализатор в своих подклассах), а затем вы можете использовать возвращаемый типSelf
дляmake()
, см., например, эти вопросы и ответы. - person Hamish   schedule 04.02.2017instantiateFromStoryboard
, поскольку вы сами их определяете. - person Hamish   schedule 05.02.2017instantiateViewController
не знает динамический тип экземпляра, который он возвращает, до времени выполнения — таким образом, он возвращает экземпляр, статически типизированный какUIViewController
. Приведение не изменяет динамический тип экземпляра — оно просто изменяет статический тип, добавляя утверждение во время выполнения, что указанный статический тип является правильным. - person Hamish   schedule 05.02.2017override class func instantiate()->Dining { // returns a "Dining"
и то же самое для всех остальных. Как только вы предпримете раздражающие усилия, чтобы вырезать и вставить их для каждого подкласса, все готово. Затем вы получаете реальный класс во время редактирования без необходимости каждый раз приводить. ууу - person Fattie   schedule 05.02.2017