Мой способ использования Координаторов с раскадровками - использование нескольких раскадровок.Одна раскадровка для каждой функции / модуля.
Почему несколько раскадровок вместо одной?При работе с большим количеством функций и в команде лучше разделить вашу раскадровку, потому что использование только одной раскадровки приведет к большому количеству конфликтов слияния , а исправление конфликтов git раскадровки - одна из трудностей того, чтобыРазработчик iOS.
Вот как я это делаю.
Сначала у меня есть протокол под названием AppStoryboardType
, который я буду реализовывать в перечислении, содержащем имена всех моих раскадровок.
protocol AppStoryboardType {
var instance: UIStoryboard { get }
func instantiate<T: UIViewController>(_ viewController: T.Type, function: String, line: Int, file: String) -> T
func instantiateInitialViewController() -> UIViewController?
}
extension AppStoryboardType {
func instantiateInitialViewController() -> UIViewController? {
return self.instance.instantiateInitialViewController()
}
}
extension AppStoryboardType where Self: RawRepresentable, Self.RawValue == String {
var instance: UIStoryboard {
return UIStoryboard(name: self.rawValue, bundle: nil)
}
func instantiate<T: UIViewController>(
_ viewController: T.Type,
function: String = #function,
line: Int = #line,
file: String = #file) -> T {
let storyboardID: String = T.storyboardIdentifier
guard let vc = self.instance.instantiateViewController(withIdentifier: storyboardID) as? T else {
fatalError("ViewController with identifier \(storyboardID), not found in \(self.rawValue) Storyboard.\nFile : \(file) \nLine Number : \(line) \nFunction : \(function)")
}
return vc
}
}
enum AppStoryboard: String, AppStoryboardType {
case Main /* ... Insert your other storyboards here. */
// These are the refactored modules that use coordinator pattern.
case PasswordRecovery, Registration
}
extension UIViewController {
public static var defaultNibName: String {
return self.description().components(separatedBy: ".").dropFirst().joined(separator: ".")
}
static var storyboardIdentifier: String {
return "\(self)"
}
static func instantiate(fromAppStoryboard appStoryboard: AppStoryboard) -> Self {
return appStoryboard.instantiate(self)
}
}
Теперь, когда я показал вам базу, которую я использую, вот как она реализована в коде.
let viewController = AppStoryboard.Login.instantiate(LoginViewController.self)
viewController./// set properties if ever you need to set them
presenter.present(viewController, animated: true, completion: nil)
PS: Большую часть времени для каждого модуля / функции у меня есть свои Раскадровка и Координатор , но это зависит от возможности многократного использования UIViewController
, который вы будете использовать.
РЕДАКТИРОВАТЬ :
1 год спустя я перестал использовать свой подход AppStoryboard
и теперь вместо него использую библиотеку Reusable .Причина этого в том, что он чище и менее подвержен человеческим ошибкам.
Теперь вместо того, чтобы программист (мы) узнал, к какой раскадровке подключен конкретный VC, теперь мы можем просто подклассировать контроллер представления вStoryboardSceneBased
, предоставьте раскадровку этого контроллера вида и создайте его экземпляр, выполнив CustomViewController.instantiate()
// From this code
let viewController = AppStoryboard.Login.instantiate(LoginViewController.self)
// To this code
let viewController = LoginViewController.instantiate()