Я приехал в Swift из Objective-C, и есть много вещей, которые Objective-C может сделать, но Swift намного сложнее.Например, динамический инициализатор ООП.
Например, у меня есть этот код, работающий в Objective-C:
@interface CommonVC: UIViewController
+ (instancetype)showFrom:(UIViewController *)vc;
@end
@implementation CommonVC
+ (instancetype)showFrom:(UIViewController *)vc {
CommonVC *instance = [self instantiateFrom:vc.nibBundle];
[vc presentViewController:instance animated:YES completion:nil];
return instance;
}
// this is like convenience initializer.
+ (instancetype)instantiateFrom:(NSBundle *)aBundle {
return [self.alloc initWithNibName:NSStringFromClass(self.class) bundle:aBundle];
}
@end
@interface SubClassVC: CommonVC
@end
И затем используйте подкласс или суперкласс, как это:
SubClassVC *subVC = [SubClassVC showFrom:self];
// or in swift:
SubClassVC.show(from: self)
Однако вбыстро, кажется, невозможно реализовать что-то подобное.Я пробовал несколько, но всегда получал ошибку компиляции.Вот один из них:
class CommonVC: UIViewController {
class func show(from sender: UIViewController) -> Self {
let vc = self(sender: sender) // Compiler error: Constructing an object of class type 'Self' with a metatype value must use a 'required' initializer
sender.present(vc, animated: true, completion: nil)
return unsafeDowncast(vc, to: self)
}
convenience init(sender: UIViewController) {
self.init(nibName: type(of: self).className, bundle: sender.nibBundle)
loadView()
}
}
Итак, как мне написать универсальный удобный инициализатор viewController из суперкласса, а затем вызвать его с помощью подкласса?
Конечно, в моем удобном init есть много вещей, которые я просто сократил до этого простого кода, также функция show(from:)
имеет другое представление вместо этого простого present(_:animated:completion:)
.
Даже если я сделаю функцию для выполнения настройки после инициализации, она все равно не будет работать
class CommonVC: UIViewController {
class func show(from sender: UIViewController) -> Self {
let vc = self.init(nibName: type(of: self).className, bundle: sender.nibBundle) // Compiler error: Constructing an object of class type 'Self' with a metatype value must use a 'required' initializer
vc.setupAfterInitialize()
sender.present(vc, animated: true, completion: nil)
return unsafeDowncast(vc, to: self)
}
convenience init(sender: UIViewController) {
self.init(nibName: type(of: self).className, bundle: sender.nibBundle)
setupAfterInitialize()
}
internal func setupAfterInitialize() {
// do stuff
loadView()
}
}
И код выглядит глупо, что не делает удобство init convenience
.
Пока я не могу использовать функцию класса show(from:)
, но перенес презентацию наружу и сделал что-то вроде:
CommonVC.show(from: self)
SubClassVC(sender: self).present()
// instead of this simple presentation:
// SubClassVC.show(from: self)
Я даже пробовал это, но все еще не работает:
class func show<T: CommonVC>(from sender: UIViewController) -> Self {
T.init(nibName: type(of: self).className, bundle: sender.nibBundle)
....