Last active
July 16, 2021 16:10
-
-
Save tonyarnold/f1a81e0f746f2e1e30eb3cd109a13a00 to your computer and use it in GitHub Desktop.
Bring some of AppKit's strongly typed names and identifiers to UIKit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
public extension UIStoryboard { | |
public struct SceneDescriptor { | |
public let name: UIStoryboard.Name | |
public let identifier: UIStoryboard.SceneIdentifier | |
public init(name: UIStoryboard.Name, identifier: UIStoryboard.SceneIdentifier) { | |
self.name = name | |
self.identifier = identifier | |
} | |
public func instantiateViewController() -> UIViewController { | |
let storyboard = UIStoryboard(name: self.name) | |
return storyboard.instantiateViewController(withIdentifier: self.identifier) | |
} | |
} | |
public struct Name: Hashable, Equatable, RawRepresentable { | |
public var rawValue: String | |
public init(rawValue: String) { | |
self.rawValue = rawValue | |
} | |
public init(_ rawValue: String) { | |
self.rawValue = rawValue | |
} | |
} | |
public struct SceneIdentifier: Hashable, Equatable, RawRepresentable { | |
public var rawValue: String | |
public init(rawValue: String) { | |
self.rawValue = rawValue | |
} | |
public init(_ rawValue: String) { | |
self.rawValue = rawValue | |
} | |
} | |
public convenience init(name: UIStoryboard.Name, bundle storyboardBundleOrNil: Bundle? = nil) { | |
self.init(name: name.rawValue, bundle: storyboardBundleOrNil) | |
} | |
public func instantiateViewController(withIdentifier identifier: UIStoryboard.SceneIdentifier) -> UIViewController { | |
return self.instantiateViewController(withIdentifier: identifier.rawValue) | |
} | |
} | |
public extension UIStoryboardSegue { | |
public struct Identifier: Hashable, Equatable, RawRepresentable { | |
public var rawValue: String | |
public init(rawValue: String) { | |
self.rawValue = rawValue | |
} | |
public init(_ rawValue: String) { | |
self.rawValue = rawValue | |
} | |
} | |
var segueIdentifier: UIStoryboardSegue.Identifier? { | |
guard let identifier = self.identifier else { | |
return nil | |
} | |
return UIStoryboardSegue.Identifier(rawValue: identifier) | |
} | |
public convenience init(identifier: UIStoryboardSegue.Identifier?, source: UIViewController, destination: UIViewController) { | |
self.init(identifier: identifier?.rawValue, source: source, destination: destination) | |
} | |
public convenience init(identifier: UIStoryboardSegue.Identifier?, source: UIViewController, destination: UIViewController, performHandler: @escaping () -> Void) { | |
self.init(identifier: identifier?.rawValue, source: source, destination: destination, performHandler: performHandler) | |
} | |
} | |
// Use a tool to scan your project and automatically generate a list of names, identifiers, etc. | |
// I wrote a tool, Resourceror, to do this for AppKit, but I'm sure it could be adapted for UIKit pretty quickly: | |
// https://github.com/tonyarnold/resourceror | |
extension UIStoryboard.Name { | |
static let login = UIStoryboard.Name(rawValue: "Login") | |
} | |
extension UIStoryboard.SceneIdentifier { | |
static let usernameEntry = UIStoryboard.SceneIdentifier(rawValue: "UsernameEntryViewControllerIdentifier") | |
static let passwordEntry = UIStoryboard.SceneIdentifier(rawValue: "PasswordEntryViewControllerIdentifier") | |
} | |
extension UIStoryboard.SceneDescriptor { | |
static let passwordEntry = UIStoryboard.SceneDescriptor(name: .login, identifier: .passwordEntry) | |
} | |
// If your method takes any of these as an argument, you can shorten their use right down to just the name preceded by a period: | |
let descriptor: UIStoryboard.SceneDescriptor = .passwordEntry | |
let viewController = descriptor.instantiateViewController() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment