Skip to content

Instantly share code, notes, and snippets.

@tonyarnold
Last active July 16, 2021 16:10
Show Gist options
  • Save tonyarnold/f1a81e0f746f2e1e30eb3cd109a13a00 to your computer and use it in GitHub Desktop.
Save tonyarnold/f1a81e0f746f2e1e30eb3cd109a13a00 to your computer and use it in GitHub Desktop.
Bring some of AppKit's strongly typed names and identifiers to UIKit
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