diff --git a/CHANGELOG.md b/CHANGELOG.md index f162755..03b8878 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,9 @@ * Since Swift 2 is no longer actively supported, we now consider those templates as "legacy" and cannot guarantee that there won't be issues with the generated code. [David Jennes](https://github.com/djbe) [#53](https://github.com/SwiftGen/templates/issues/53) +* The iOS and macOS storyboard templates have been unified into one. The generated code also no longer uses enum cases for scenes but instead uses a generic struct. See the documentation for some examples. + [David Jennes](https://github.com/djbe) + [#57](https://github.com/SwiftGen/templates/issues/57) ### New Features diff --git a/Documentation/MigrationGuide.md b/Documentation/MigrationGuide.md index 9a41f20..0a69592 100644 --- a/Documentation/MigrationGuide.md +++ b/Documentation/MigrationGuide.md @@ -36,9 +36,9 @@ Below is a list of renamed and removed templates, grouped by subcommand. If your | --- | --- | ------ | | default | swift2 | | | lowercase | **deleted** | No longer needed since we prefix classes with their module | -| osx-default | macOS-swift2 | | +| osx-default | **deleted** | Unified with the iOS template, just use `swift2` | | osx-lowercase | **deleted** | No longer needed since we prefix classes with their module | -| osx-swift3 | macOS-swift3 | | +| osx-swift3 | **deleted** | Unified with the iOS template, just use `swift3` | | uppercase | **deleted** | No longer needed since we prefix classes with their module | ### Strings ### diff --git a/Documentation/storyboards/macOS-swift2.md b/Documentation/storyboards/macOS-swift2.md deleted file mode 100644 index 4215c6e..0000000 --- a/Documentation/storyboards/macOS-swift2.md +++ /dev/null @@ -1,87 +0,0 @@ -## Template Information - -| Name | Description | -| --------- | ----------------- | -| File name | storyboards/macOS-swift2.stencil | -| Invocation example | `swiftgen storyboards -t macOS-swift2 …` | -| Language | Swift 2 | -| Author | Olivier Halligon | - -## When to use it - -- When you need to generate *Swift 2* code -- You want to generate code for AppKit platforms (macOS). -- **Warning**: Swift 2 is no longer actively supported, so we cannot guarantee that there won't be issues with the generated code. - -## Customization - -You can customize some elements of this template by overriding the following parameters when invoking `swiftgen` in the command line, using `--param =` - -| Parameter Name | Default Value | Description | -| -------------- | ------------- | ----------- | -| `sceneEnumName` | `StoryboardScene` | Allows you to change the name of the generated `enum` containing all storyboard scenes. | -| `segueEnumName` | `StoryboardSegue` | Allows you to change the name of the generated `enum` containing all storyboard segues. | - -## Generated Code - -**Extract:** - -```swift -enum StoryboardScene { - enum Dependency: String, StoryboardSceneType { - static let storyboardName = "Dependency" - - case DependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.DependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } - } - enum Message: String, StoryboardSceneType { - static let storyboardName = "Message" - - case MessageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } - } -} -enum StoryboardSegue { - enum Message: String, StoryboardSegueType { - case Embed - case Modal - } -} -``` - -[Full generated code](https://github.com/SwiftGen/templates/blob/master/Tests/Expected/Storyboards-macOS/swift2-context-all.swift) - -## Usage example - -```swift -// You can instantiate scenes using the generic `controller()` method: -let vc = StoryboardScene.Dependency.DependentScene.controller() - -// or the `instantiate...()` method (which will cast to the correct type): -let vc2 = StoryboardScene.Message.instantiateMessageList() - -// You can perform segues using: -vc.performSegue(StoryboardSegue.Message.Embed) - -// or match them (in prepareForSegue): -override func prepareForSegue(_ segue: NSStoryboardSegue, sender sender: AnyObject?) { - switch StoryboardSegue.Message(rawValue: segue.identifier!)! { - case .Embed: - // Prepare for your custom segue transition - case .Modal: - // Pass in information to the destination View Controller - } -} -``` diff --git a/Documentation/storyboards/macOS-swift3.md b/Documentation/storyboards/macOS-swift3.md deleted file mode 100644 index 4b88b38..0000000 --- a/Documentation/storyboards/macOS-swift3.md +++ /dev/null @@ -1,86 +0,0 @@ -## Template Information - -| Name | Description | -| --------- | ----------------- | -| File name | storyboards/macOS-swift3.stencil | -| Invocation example | `swiftgen storyboards -t macOS-swift3 …` | -| Language | Swift 3 | -| Author | Olivier Halligon | - -## When to use it - -- When you need to generate *Swift 3* code -- You want to generate code for AppKit platforms (macOS). - -## Customization - -You can customize some elements of this template by overriding the following parameters when invoking `swiftgen` in the command line, using `--param =` - -| Parameter Name | Default Value | Description | -| -------------- | ------------- | ----------- | -| `sceneEnumName` | `StoryboardScene` | Allows you to change the name of the generated `enum` containing all storyboard scenes. | -| `segueEnumName` | `StoryboardSegue` | Allows you to change the name of the generated `enum` containing all storyboard segues. | - -## Generated Code - -**Extract:** - -```swift -enum StoryboardScene { - enum Dependency: String, StoryboardSceneType { - static let storyboardName = "Dependency" - - case dependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.dependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } - } - enum Message: String, StoryboardSceneType { - static let storyboardName = "Message" - - case messageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.messageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } - } -} -enum StoryboardSegue { - enum Message: String, StoryboardSegueType { - case embed - case modal - } -} -``` - -[Full generated code](https://github.com/SwiftGen/templates/blob/master/Tests/Expected/Storyboards-macOS/swift3-context-all.swift) - -## Usage example - -```swift -// You can instantiate scenes using the generic `controller()` method: -let vc = StoryboardScene.Dependency.dependentScene.controller() - -// or the `instantiate...()` method (which will cast to the correct type): -let vc2 = StoryboardScene.Message.instantiateMessageList() - -// You can perform segues using: -vc.perform(segue: StoryboardSegue.Message.embed) - -// or match them (in prepareForSegue): -override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - switch UIStoryboard.Segue.Message(rawValue: segue.identifier!)! { - case .embed: - // Prepare for your custom segue transition - case .modal: - // Pass in information to the destination View Controller - } -} -``` diff --git a/Documentation/storyboards/swift2.md b/Documentation/storyboards/swift2.md index 7b080f3..4df9258 100644 --- a/Documentation/storyboards/swift2.md +++ b/Documentation/storyboards/swift2.md @@ -10,8 +10,8 @@ ## When to use it - When you need to generate *Swift 2* code -- You want to generate code for UIKit platforms (iOS, tvOS and watchOS) -- **Warning**: Swift 2 is no longer actively supported, so we cannot guarantee that there won't be issues with the generated code. +- The generated code supports both UIKit platforms (iOS, tvOS and watchOS) and AppKit platform (macOS) +- **Warning**: Swift 2 is no longer actively supported, so we won't maintain this template and don't unit-test the generated code for it anymore. ## Customization @@ -24,33 +24,25 @@ You can customize some elements of this template by overriding the following par ## Generated Code +Note: the generated code may look differently depending on the platform the storyboard file is targeting. + **Extract:** ```swift enum StoryboardScene { - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.DependentScene.viewController() - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case MessagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.MessagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let MessagesList = SceneType(Message.self, identifier: "MessagesList") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case Embed case NonCustom } @@ -62,11 +54,8 @@ enum StoryboardSegue { ## Usage example ```swift -// You can instantiate scenes using the generic `viewController()` method: -let vc = StoryboardScene.Dependency.DependentScene.viewController() - -// or the `instantiate...()` method (which will cast to the correct type): -let vc2 = StoryboardScene.Message.instantiateMessagesList() +// You can instantiate scenes using the `controller` property: +let vc = StoryboardScene.Dependency.Dependent.controller // You can perform segues using: vc.performSegue(StoryboardSegue.Message.Embed) diff --git a/Documentation/storyboards/swift3.md b/Documentation/storyboards/swift3.md index 035956d..fd3a27a 100644 --- a/Documentation/storyboards/swift3.md +++ b/Documentation/storyboards/swift3.md @@ -10,7 +10,7 @@ ## When to use it - When you need to generate *Swift 3* code -- You want to generate code for UIKit platforms (iOS, tvOS and watchOS) +- The generated code supports both UIKit platforms (iOS, tvOS and watchOS) and AppKit platform (macOS) ## Customization @@ -23,33 +23,25 @@ You can customize some elements of this template by overriding the following par ## Generated Code +Note: the generated code may look differently depending on the platform the storyboard file is targeting. + **Extract:** ```swift enum StoryboardScene { - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.dependentScene.viewController() - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case messagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.messagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case embed case nonCustom } @@ -61,11 +53,8 @@ enum StoryboardSegue { ## Usage example ```swift -// You can instantiate scenes using the generic `viewController()` method: -let vc = StoryboardScene.Dependency.dependentScene.viewController() - -// or the `instantiate...()` method (which will cast to the correct type): -let vc2 = StoryboardScene.Message.instantiateMessagesList() +// You can instantiate scenes using the `controller` property: +let vc = StoryboardScene.Dependency.dependent.controller // You can perform segues using: vc.perform(segue: StoryboardSegue.Message.embed) diff --git a/Tests/Expected/Storyboards-iOS/swift2-context-all-customname.swift b/Tests/Expected/Storyboards-iOS/swift2-context-all-customname.swift index 40cb14e..69e7bf2 100644 --- a/Tests/Expected/Storyboards-iOS/swift2-context-all-customname.swift +++ b/Tests/Expected/Storyboards-iOS/swift2-context-all-customname.swift @@ -9,177 +9,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewControllerWithIdentifier(self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { + func performSegue(segue: S, sender: AnyObject? = nil) { performSegueWithIdentifier(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum XCTStoryboardsScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(AdditionalImport.self) - case PublicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = XCTStoryboardsScene.AdditionalImport.PublicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let Public = SceneType(AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return XCTStoryboardsScene.Dependency.DependentScene.viewController() - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case ComposerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return XCTStoryboardsScene.Message.ComposerScene.viewController() - } + static let initialScene = InitialSceneType(Message.self) - case MessagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = XCTStoryboardsScene.Message.MessagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let Composer = SceneType(Message.self, identifier: "Composer") - case NavCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = XCTStoryboardsScene.Message.NavCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let MessagesList = SceneType(Message.self, identifier: "MessagesList") - case URLChooserScene = "URLChooser" - static func instantiateURLChooser() -> XXPickerViewController { - guard let vc = XCTStoryboardsScene.Message.URLChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let NavCtrl = SceneType(Message.self, identifier: "NavCtrl") + + static let URLChooser = SceneType(Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case NavigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = XCTStoryboardsScene.Placeholder.NavigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let Navigation = SceneType(Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Wizard.self) - case Accept_CGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return XCTStoryboardsScene.Wizard.Accept_CGUScene.viewController() - } + static let Accept_CGU = SceneType(Wizard.self, identifier: "Accept-CGU") - case CreateAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = XCTStoryboardsScene.Wizard.CreateAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let CreateAccount = SceneType(Wizard.self, identifier: "CreateAccount") - case PreferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = XCTStoryboardsScene.Wizard.PreferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let Preferences = SceneType(Wizard.self, identifier: "Preferences") - case Validate_PasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return XCTStoryboardsScene.Wizard.Validate_PasswordScene.viewController() - } + static let Validate_Password = SceneType(Wizard.self, identifier: "Validate_Password") } } enum XCTStoryboardsSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case Private = "private" } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case CustomBack case Embed case NonCustom case Show_NavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case ShowPassword } } diff --git a/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module.swift b/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module.swift index 8ea3d73..408a5bb 100644 --- a/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module.swift +++ b/Tests/Expected/Storyboards-iOS/swift2-context-all-ignore-module.swift @@ -8,177 +8,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewControllerWithIdentifier(self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { + func performSegue(segue: S, sender: AnyObject? = nil) { performSegueWithIdentifier(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(AdditionalImport.self) - case PublicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = StoryboardScene.AdditionalImport.PublicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let Public = SceneType(AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.DependentScene.viewController() - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case ComposerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return StoryboardScene.Message.ComposerScene.viewController() - } + static let initialScene = InitialSceneType(Message.self) - case MessagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.MessagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let Composer = SceneType(Message.self, identifier: "Composer") - case NavCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = StoryboardScene.Message.NavCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let MessagesList = SceneType(Message.self, identifier: "MessagesList") - case URLChooserScene = "URLChooser" - static func instantiateURLChooser() -> XXPickerViewController { - guard let vc = StoryboardScene.Message.URLChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let NavCtrl = SceneType(Message.self, identifier: "NavCtrl") + + static let URLChooser = SceneType(Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case NavigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = StoryboardScene.Placeholder.NavigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let Navigation = SceneType(Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Wizard.self) - case Accept_CGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return StoryboardScene.Wizard.Accept_CGUScene.viewController() - } + static let Accept_CGU = SceneType(Wizard.self, identifier: "Accept-CGU") - case CreateAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = StoryboardScene.Wizard.CreateAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let CreateAccount = SceneType(Wizard.self, identifier: "CreateAccount") - case PreferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = StoryboardScene.Wizard.PreferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let Preferences = SceneType(Wizard.self, identifier: "Preferences") - case Validate_PasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return StoryboardScene.Wizard.Validate_PasswordScene.viewController() - } + static let Validate_Password = SceneType(Wizard.self, identifier: "Validate_Password") } } enum StoryboardSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case Private = "private" } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case CustomBack case Embed case NonCustom case Show_NavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case ShowPassword } } diff --git a/Tests/Expected/Storyboards-iOS/swift2-context-all.swift b/Tests/Expected/Storyboards-iOS/swift2-context-all.swift index c4f4256..b8f27a1 100644 --- a/Tests/Expected/Storyboards-iOS/swift2-context-all.swift +++ b/Tests/Expected/Storyboards-iOS/swift2-context-all.swift @@ -9,177 +9,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewControllerWithIdentifier(self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { + func performSegue(segue: S, sender: AnyObject? = nil) { performSegueWithIdentifier(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(AdditionalImport.self) - case PublicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = StoryboardScene.AdditionalImport.PublicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let Public = SceneType(AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.DependentScene.viewController() - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case ComposerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return StoryboardScene.Message.ComposerScene.viewController() - } + static let initialScene = InitialSceneType(Message.self) - case MessagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.MessagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let Composer = SceneType(Message.self, identifier: "Composer") - case NavCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = StoryboardScene.Message.NavCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let MessagesList = SceneType(Message.self, identifier: "MessagesList") - case URLChooserScene = "URLChooser" - static func instantiateURLChooser() -> XXPickerViewController { - guard let vc = StoryboardScene.Message.URLChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let NavCtrl = SceneType(Message.self, identifier: "NavCtrl") + + static let URLChooser = SceneType(Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case NavigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = StoryboardScene.Placeholder.NavigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let Navigation = SceneType(Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(Wizard.self) - case Accept_CGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return StoryboardScene.Wizard.Accept_CGUScene.viewController() - } + static let Accept_CGU = SceneType(Wizard.self, identifier: "Accept-CGU") - case CreateAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = StoryboardScene.Wizard.CreateAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let CreateAccount = SceneType(Wizard.self, identifier: "CreateAccount") - case PreferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = StoryboardScene.Wizard.PreferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let Preferences = SceneType(Wizard.self, identifier: "Preferences") - case Validate_PasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return StoryboardScene.Wizard.Validate_PasswordScene.viewController() - } + static let Validate_Password = SceneType(Wizard.self, identifier: "Validate_Password") } } enum StoryboardSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case Private = "private" } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case CustomBack case Embed case NonCustom case Show_NavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case ShowPassword } } diff --git a/Tests/Expected/Storyboards-iOS/swift3-context-all-customname.swift b/Tests/Expected/Storyboards-iOS/swift3-context-all-customname.swift index f184372..b403ecf 100644 --- a/Tests/Expected/Storyboards-iOS/swift3-context-all-customname.swift +++ b/Tests/Expected/Storyboards-iOS/swift3-context-all-customname.swift @@ -9,177 +9,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewController(withIdentifier: self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { performSegue(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum XCTStoryboardsScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: AdditionalImport.self) - case publicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = XCTStoryboardsScene.AdditionalImport.publicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let `public` = SceneType(storyboard: AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return XCTStoryboardsScene.Dependency.dependentScene.viewController() - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case composerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return XCTStoryboardsScene.Message.composerScene.viewController() - } + static let initialScene = InitialSceneType(storyboard: Message.self) - case messagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = XCTStoryboardsScene.Message.messagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let composer = SceneType(storyboard: Message.self, identifier: "Composer") - case navCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = XCTStoryboardsScene.Message.navCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") - case urlChooserScene = "URLChooser" - static func instantiateUrlChooser() -> XXPickerViewController { - guard let vc = XCTStoryboardsScene.Message.urlChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let navCtrl = SceneType(storyboard: Message.self, identifier: "NavCtrl") + + static let urlChooser = SceneType(storyboard: Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case navigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = XCTStoryboardsScene.Placeholder.navigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let navigation = SceneType(storyboard: Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Wizard.self) - case acceptCGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return XCTStoryboardsScene.Wizard.acceptCGUScene.viewController() - } + static let acceptCGU = SceneType(storyboard: Wizard.self, identifier: "Accept-CGU") - case createAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = XCTStoryboardsScene.Wizard.createAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let createAccount = SceneType(storyboard: Wizard.self, identifier: "CreateAccount") - case preferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = XCTStoryboardsScene.Wizard.preferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let preferences = SceneType(storyboard: Wizard.self, identifier: "Preferences") - case validatePasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return XCTStoryboardsScene.Wizard.validatePasswordScene.viewController() - } + static let validatePassword = SceneType(storyboard: Wizard.self, identifier: "Validate_Password") } } enum XCTStoryboardsSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case `private` } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case customBack = "CustomBack" case embed = "Embed" case nonCustom = "NonCustom" case showNavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case showPassword = "ShowPassword" } } diff --git a/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module.swift b/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module.swift index ed9228d..132a3ab 100644 --- a/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module.swift +++ b/Tests/Expected/Storyboards-iOS/swift3-context-all-ignore-module.swift @@ -8,177 +8,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewController(withIdentifier: self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { performSegue(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: AdditionalImport.self) - case publicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = StoryboardScene.AdditionalImport.publicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let `public` = SceneType(storyboard: AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.dependentScene.viewController() - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case composerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return StoryboardScene.Message.composerScene.viewController() - } + static let initialScene = InitialSceneType(storyboard: Message.self) - case messagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.messagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let composer = SceneType(storyboard: Message.self, identifier: "Composer") - case navCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = StoryboardScene.Message.navCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") - case urlChooserScene = "URLChooser" - static func instantiateUrlChooser() -> XXPickerViewController { - guard let vc = StoryboardScene.Message.urlChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let navCtrl = SceneType(storyboard: Message.self, identifier: "NavCtrl") + + static let urlChooser = SceneType(storyboard: Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case navigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = StoryboardScene.Placeholder.navigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let navigation = SceneType(storyboard: Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Wizard.self) - case acceptCGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return StoryboardScene.Wizard.acceptCGUScene.viewController() - } + static let acceptCGU = SceneType(storyboard: Wizard.self, identifier: "Accept-CGU") - case createAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = StoryboardScene.Wizard.createAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let createAccount = SceneType(storyboard: Wizard.self, identifier: "CreateAccount") - case preferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = StoryboardScene.Wizard.preferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let preferences = SceneType(storyboard: Wizard.self, identifier: "Preferences") - case validatePasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return StoryboardScene.Wizard.validatePasswordScene.viewController() - } + static let validatePassword = SceneType(storyboard: Wizard.self, identifier: "Validate_Password") } } enum StoryboardSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case `private` } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case customBack = "CustomBack" case embed = "Embed" case nonCustom = "NonCustom" case showNavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case showPassword = "ShowPassword" } } diff --git a/Tests/Expected/Storyboards-iOS/swift3-context-all.swift b/Tests/Expected/Storyboards-iOS/swift3-context-all.swift index 629346d..c5d74b1 100644 --- a/Tests/Expected/Storyboards-iOS/swift3-context-all.swift +++ b/Tests/Expected/Storyboards-iOS/swift3-context-all.swift @@ -9,177 +9,110 @@ import SlackTextViewController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { +extension StoryboardType { + static var storyboard: UIStoryboard { return UIStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} + +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") + var controller: T { + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewController(withIdentifier: self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } extension UIViewController { - func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { performSegue(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - static func initialViewController() -> LocationPicker.LocationPickerViewController { - guard let vc = storyboard().instantiateInitialViewController() as? LocationPicker.LocationPickerViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: AdditionalImport.self) - case publicScene = "public" - static func instantiatePublic() -> SlackTextViewController.SLKTextViewController { - guard let vc = StoryboardScene.AdditionalImport.publicScene.viewController() as? SlackTextViewController.SLKTextViewController - else { - fatalError("ViewController 'public' is not of the expected class SlackTextViewController.SLKTextViewController.") - } - return vc - } + static let `public` = SceneType(storyboard: AdditionalImport.self, identifier: "public") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" - static func initialViewController() -> UINavigationController { - guard let vc = storyboard().instantiateInitialViewController() as? UINavigationController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Anonymous.self) } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> UIViewController { - return StoryboardScene.Dependency.dependentScene.viewController() - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case composerScene = "Composer" - static func instantiateComposer() -> UIViewController { - return StoryboardScene.Message.composerScene.viewController() - } + static let initialScene = InitialSceneType(storyboard: Message.self) - case messagesListScene = "MessagesList" - static func instantiateMessagesList() -> UITableViewController { - guard let vc = StoryboardScene.Message.messagesListScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'MessagesList' is not of the expected class UITableViewController.") - } - return vc - } + static let composer = SceneType(storyboard: Message.self, identifier: "Composer") - case navCtrlScene = "NavCtrl" - static func instantiateNavCtrl() -> UINavigationController { - guard let vc = StoryboardScene.Message.navCtrlScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'NavCtrl' is not of the expected class UINavigationController.") - } - return vc - } + static let messagesList = SceneType(storyboard: Message.self, identifier: "MessagesList") - case urlChooserScene = "URLChooser" - static func instantiateUrlChooser() -> XXPickerViewController { - guard let vc = StoryboardScene.Message.urlChooserScene.viewController() as? XXPickerViewController - else { - fatalError("ViewController 'URLChooser' is not of the expected class XXPickerViewController.") - } - return vc - } + static let navCtrl = SceneType(storyboard: Message.self, identifier: "NavCtrl") + + static let urlChooser = SceneType(storyboard: Message.self, identifier: "URLChooser") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case navigationScene = "Navigation" - static func instantiateNavigation() -> UINavigationController { - guard let vc = StoryboardScene.Placeholder.navigationScene.viewController() as? UINavigationController - else { - fatalError("ViewController 'Navigation' is not of the expected class UINavigationController.") - } - return vc - } + static let navigation = SceneType(storyboard: Placeholder.self, identifier: "Navigation") } - enum Wizard: String, StoryboardSceneType { + enum Wizard: StoryboardType { static let storyboardName = "Wizard" - static func initialViewController() -> CreateAccViewController { - guard let vc = storyboard().instantiateInitialViewController() as? CreateAccViewController else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + static let initialScene = InitialSceneType(storyboard: Wizard.self) - case acceptCGUScene = "Accept-CGU" - static func instantiateAcceptCGU() -> UIViewController { - return StoryboardScene.Wizard.acceptCGUScene.viewController() - } + static let acceptCGU = SceneType(storyboard: Wizard.self, identifier: "Accept-CGU") - case createAccountScene = "CreateAccount" - static func instantiateCreateAccount() -> CreateAccViewController { - guard let vc = StoryboardScene.Wizard.createAccountScene.viewController() as? CreateAccViewController - else { - fatalError("ViewController 'CreateAccount' is not of the expected class CreateAccViewController.") - } - return vc - } + static let createAccount = SceneType(storyboard: Wizard.self, identifier: "CreateAccount") - case preferencesScene = "Preferences" - static func instantiatePreferences() -> UITableViewController { - guard let vc = StoryboardScene.Wizard.preferencesScene.viewController() as? UITableViewController - else { - fatalError("ViewController 'Preferences' is not of the expected class UITableViewController.") - } - return vc - } + static let preferences = SceneType(storyboard: Wizard.self, identifier: "Preferences") - case validatePasswordScene = "Validate_Password" - static func instantiateValidatePassword() -> UIViewController { - return StoryboardScene.Wizard.validatePasswordScene.viewController() - } + static let validatePassword = SceneType(storyboard: Wizard.self, identifier: "Validate_Password") } } enum StoryboardSegue { - enum AdditionalImport: String, StoryboardSegueType { + enum AdditionalImport: String, SegueType { case `private` } - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case customBack = "CustomBack" case embed = "Embed" case nonCustom = "NonCustom" case showNavCtrl = "Show-NavCtrl" } - enum Wizard: String, StoryboardSegueType { + enum Wizard: String, SegueType { case showPassword = "ShowPassword" } } diff --git a/Tests/Expected/Storyboards-macOS/swift2-context-all-customname.swift b/Tests/Expected/Storyboards-macOS/swift2-context-all-customname.swift index cb31cbe..1bfd508 100644 --- a/Tests/Expected/Storyboards-macOS/swift2-context-all-customname.swift +++ b/Tests/Expected/Storyboards-macOS/swift2-context-all-customname.swift @@ -1,165 +1,95 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import FadeSegue import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} - static func initialController() -> AnyObject { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> AnyObject { - return Self.storyboard().instantiateControllerWithIdentifier(self.rawValue) - } - static func controller(identifier: Self) -> AnyObject { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier?(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum XCTStoryboardsScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case PrivateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = XCTStoryboardsScene.AdditionalImport.PrivateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let Private = SceneType(AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = XCTStoryboardsScene.Dependency.DependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case MessageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.MessageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let MessageDetails = SceneType(Message.self, identifier: "MessageDetails") - case MessageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.MessageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let MessageList = SceneType(Message.self, identifier: "MessageList") - case MessageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.MessageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let MessageListFooter = SceneType(Message.self, identifier: "MessageListFooter") - case MessagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = XCTStoryboardsScene.Message.MessagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let MessagesTab = SceneType(Message.self, identifier: "MessagesTab") - case SplitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = XCTStoryboardsScene.Message.SplitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let SplitMessages = SceneType(Message.self, identifier: "SplitMessages") - case WindowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = XCTStoryboardsScene.Message.WindowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let WindowCtrl = SceneType(Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = XCTStoryboardsScene.Placeholder.DependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let Dependent = SceneType(Placeholder.self, identifier: "Dependent") - case WindowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = XCTStoryboardsScene.Placeholder.WindowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let Window = SceneType(Placeholder.self, identifier: "Window") } } enum XCTStoryboardsSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case Embed case Modal case Popover diff --git a/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module.swift b/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module.swift index 03c5497..ca0d367 100644 --- a/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module.swift +++ b/Tests/Expected/Storyboards-macOS/swift2-context-all-ignore-module.swift @@ -1,164 +1,94 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} - static func initialController() -> AnyObject { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> AnyObject { - return Self.storyboard().instantiateControllerWithIdentifier(self.rawValue) - } - static func controller(identifier: Self) -> AnyObject { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier?(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case PrivateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = StoryboardScene.AdditionalImport.PrivateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let Private = SceneType(AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.DependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case MessageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let MessageDetails = SceneType(Message.self, identifier: "MessageDetails") - case MessageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let MessageList = SceneType(Message.self, identifier: "MessageList") - case MessageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let MessageListFooter = SceneType(Message.self, identifier: "MessageListFooter") - case MessagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = StoryboardScene.Message.MessagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let MessagesTab = SceneType(Message.self, identifier: "MessagesTab") - case SplitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = StoryboardScene.Message.SplitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let SplitMessages = SceneType(Message.self, identifier: "SplitMessages") - case WindowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = StoryboardScene.Message.WindowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let WindowCtrl = SceneType(Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = StoryboardScene.Placeholder.DependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let Dependent = SceneType(Placeholder.self, identifier: "Dependent") - case WindowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = StoryboardScene.Placeholder.WindowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let Window = SceneType(Placeholder.self, identifier: "Window") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case Embed case Modal case Popover diff --git a/Tests/Expected/Storyboards-macOS/swift2-context-all.swift b/Tests/Expected/Storyboards-macOS/swift2-context-all.swift index f041635..2e32043 100644 --- a/Tests/Expected/Storyboards-macOS/swift2-context-all.swift +++ b/Tests/Expected/Storyboards-macOS/swift2-context-all.swift @@ -1,165 +1,95 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import FadeSegue import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} - static func initialController() -> AnyObject { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateControllerWithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> AnyObject { - return Self.storyboard().instantiateControllerWithIdentifier(self.rawValue) - } - static func controller(identifier: Self) -> AnyObject { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier?(segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case PrivateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = StoryboardScene.AdditionalImport.PrivateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let Private = SceneType(AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.DependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let Dependent = SceneType(Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case MessageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let MessageDetails = SceneType(Message.self, identifier: "MessageDetails") - case MessageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let MessageList = SceneType(Message.self, identifier: "MessageList") - case MessageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = StoryboardScene.Message.MessageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let MessageListFooter = SceneType(Message.self, identifier: "MessageListFooter") - case MessagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = StoryboardScene.Message.MessagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let MessagesTab = SceneType(Message.self, identifier: "MessagesTab") - case SplitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = StoryboardScene.Message.SplitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let SplitMessages = SceneType(Message.self, identifier: "SplitMessages") - case WindowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = StoryboardScene.Message.WindowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let WindowCtrl = SceneType(Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case DependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = StoryboardScene.Placeholder.DependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let Dependent = SceneType(Placeholder.self, identifier: "Dependent") - case WindowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = StoryboardScene.Placeholder.WindowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let Window = SceneType(Placeholder.self, identifier: "Window") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case Embed case Modal case Popover diff --git a/Tests/Expected/Storyboards-macOS/swift3-context-all-customname.swift b/Tests/Expected/Storyboards-macOS/swift3-context-all-customname.swift index e268ddf..446e1cf 100644 --- a/Tests/Expected/Storyboards-macOS/swift3-context-all-customname.swift +++ b/Tests/Expected/Storyboards-macOS/swift3-context-all-customname.swift @@ -1,165 +1,95 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import FadeSegue import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} - static func initialController() -> Any { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> Any { - return Self.storyboard().instantiateController(withIdentifier: self.rawValue) - } - static func controller(identifier: Self) -> Any { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue?(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum XCTStoryboardsScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case privateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = XCTStoryboardsScene.AdditionalImport.privateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let `private` = SceneType(storyboard: AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = XCTStoryboardsScene.Dependency.dependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case messageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.messageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let messageDetails = SceneType(storyboard: Message.self, identifier: "MessageDetails") - case messageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.messageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let messageList = SceneType(storyboard: Message.self, identifier: "MessageList") - case messageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = XCTStoryboardsScene.Message.messageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let messageListFooter = SceneType(storyboard: Message.self, identifier: "MessageListFooter") - case messagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = XCTStoryboardsScene.Message.messagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let messagesTab = SceneType(storyboard: Message.self, identifier: "MessagesTab") - case splitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = XCTStoryboardsScene.Message.splitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let splitMessages = SceneType(storyboard: Message.self, identifier: "SplitMessages") - case windowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = XCTStoryboardsScene.Message.windowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let windowCtrl = SceneType(storyboard: Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = XCTStoryboardsScene.Placeholder.dependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let dependent = SceneType(storyboard: Placeholder.self, identifier: "Dependent") - case windowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = XCTStoryboardsScene.Placeholder.windowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let window = SceneType(storyboard: Placeholder.self, identifier: "Window") } } enum XCTStoryboardsSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case embed = "Embed" case modal = "Modal" case popover = "Popover" diff --git a/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module.swift b/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module.swift index a603b97..9931444 100644 --- a/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module.swift +++ b/Tests/Expected/Storyboards-macOS/swift3-context-all-ignore-module.swift @@ -1,164 +1,94 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} - static func initialController() -> Any { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> Any { - return Self.storyboard().instantiateController(withIdentifier: self.rawValue) - } - static func controller(identifier: Self) -> Any { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue?(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case privateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = StoryboardScene.AdditionalImport.privateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let `private` = SceneType(storyboard: AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.dependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case messageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = StoryboardScene.Message.messageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let messageDetails = SceneType(storyboard: Message.self, identifier: "MessageDetails") - case messageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.messageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let messageList = SceneType(storyboard: Message.self, identifier: "MessageList") - case messageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = StoryboardScene.Message.messageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let messageListFooter = SceneType(storyboard: Message.self, identifier: "MessageListFooter") - case messagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = StoryboardScene.Message.messagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let messagesTab = SceneType(storyboard: Message.self, identifier: "MessagesTab") - case splitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = StoryboardScene.Message.splitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let splitMessages = SceneType(storyboard: Message.self, identifier: "SplitMessages") - case windowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = StoryboardScene.Message.windowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let windowCtrl = SceneType(storyboard: Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = StoryboardScene.Placeholder.dependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let dependent = SceneType(storyboard: Placeholder.self, identifier: "Dependent") - case windowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = StoryboardScene.Placeholder.windowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let window = SceneType(storyboard: Placeholder.self, identifier: "Window") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case embed = "Embed" case modal = "Modal" case popover = "Popover" diff --git a/Tests/Expected/Storyboards-macOS/swift3-context-all.swift b/Tests/Expected/Storyboards-macOS/swift3-context-all.swift index bd3774c..77b82a9 100644 --- a/Tests/Expected/Storyboards-macOS/swift3-context-all.swift +++ b/Tests/Expected/Storyboards-macOS/swift3-context-all.swift @@ -1,165 +1,95 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen // swiftlint:disable sorted_imports -import Cocoa import Foundation +import Cocoa import FadeSegue import PrefsWindowController // swiftlint:disable file_length -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { +extension StoryboardType { + static var storyboard: NSStoryboard { return NSStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} - static func initialController() -> Any { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiateController(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> Any { - return Self.storyboard().instantiateController(withIdentifier: self.rawValue) - } - static func controller(identifier: Self) -> Any { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } +struct InitialSceneType { + let storyboard: StoryboardType.Type -extension NSWindowController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitialController() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -extension NSViewController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) +protocol SegueType: RawRepresentable { } + +extension NSSeguePerforming { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue?(withIdentifier: segue.rawValue, sender: sender) } } // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name enum StoryboardScene { - enum AdditionalImport: String, StoryboardSceneType { + enum AdditionalImport: StoryboardType { static let storyboardName = "AdditionalImport" - case privateScene = "private" - static func instantiatePrivate() -> PrefsWindowController.DBPrefsWindowController { - guard let vc = StoryboardScene.AdditionalImport.privateScene.controller() as? PrefsWindowController.DBPrefsWindowController - else { - fatalError("ViewController 'private' is not of the expected class PrefsWindowController.DBPrefsWindowController.") - } - return vc - } + static let `private` = SceneType(storyboard: AdditionalImport.self, identifier: "private") } - enum Anonymous: StoryboardSceneType { + enum Anonymous: StoryboardType { static let storyboardName = "Anonymous" } - enum Dependency: String, StoryboardSceneType { + enum Dependency: StoryboardType { static let storyboardName = "Dependency" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSViewController { - guard let vc = StoryboardScene.Dependency.dependentScene.controller() as? NSViewController - else { - fatalError("ViewController 'Dependent' is not of the expected class NSViewController.") - } - return vc - } + static let dependent = SceneType(storyboard: Dependency.self, identifier: "Dependent") } - enum Message: String, StoryboardSceneType { + enum Message: StoryboardType { static let storyboardName = "Message" - case messageDetailsScene = "MessageDetails" - static func instantiateMessageDetails() -> NSViewController { - guard let vc = StoryboardScene.Message.messageDetailsScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageDetails' is not of the expected class NSViewController.") - } - return vc - } + static let messageDetails = SceneType(storyboard: Message.self, identifier: "MessageDetails") - case messageListScene = "MessageList" - static func instantiateMessageList() -> NSViewController { - guard let vc = StoryboardScene.Message.messageListScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageList' is not of the expected class NSViewController.") - } - return vc - } + static let messageList = SceneType(storyboard: Message.self, identifier: "MessageList") - case messageListFooterScene = "MessageListFooter" - static func instantiateMessageListFooter() -> NSViewController { - guard let vc = StoryboardScene.Message.messageListFooterScene.controller() as? NSViewController - else { - fatalError("ViewController 'MessageListFooter' is not of the expected class NSViewController.") - } - return vc - } + static let messageListFooter = SceneType(storyboard: Message.self, identifier: "MessageListFooter") - case messagesTabScene = "MessagesTab" - static func instantiateMessagesTab() -> CustomTabViewController { - guard let vc = StoryboardScene.Message.messagesTabScene.controller() as? CustomTabViewController - else { - fatalError("ViewController 'MessagesTab' is not of the expected class CustomTabViewController.") - } - return vc - } + static let messagesTab = SceneType(storyboard: Message.self, identifier: "MessagesTab") - case splitMessagesScene = "SplitMessages" - static func instantiateSplitMessages() -> NSSplitViewController { - guard let vc = StoryboardScene.Message.splitMessagesScene.controller() as? NSSplitViewController - else { - fatalError("ViewController 'SplitMessages' is not of the expected class NSSplitViewController.") - } - return vc - } + static let splitMessages = SceneType(storyboard: Message.self, identifier: "SplitMessages") - case windowCtrlScene = "WindowCtrl" - static func instantiateWindowCtrl() -> NSWindowController { - guard let vc = StoryboardScene.Message.windowCtrlScene.controller() as? NSWindowController - else { - fatalError("ViewController 'WindowCtrl' is not of the expected class NSWindowController.") - } - return vc - } + static let windowCtrl = SceneType(storyboard: Message.self, identifier: "WindowCtrl") } - enum Placeholder: String, StoryboardSceneType { + enum Placeholder: StoryboardType { static let storyboardName = "Placeholder" - case dependentScene = "Dependent" - static func instantiateDependent() -> NSControllerPlaceholder { - guard let vc = StoryboardScene.Placeholder.dependentScene.controller() as? NSControllerPlaceholder - else { - fatalError("ViewController 'Dependent' is not of the expected class NSControllerPlaceholder.") - } - return vc - } + static let dependent = SceneType(storyboard: Placeholder.self, identifier: "Dependent") - case windowScene = "Window" - static func instantiateWindow() -> NSWindowController { - guard let vc = StoryboardScene.Placeholder.windowScene.controller() as? NSWindowController - else { - fatalError("ViewController 'Window' is not of the expected class NSWindowController.") - } - return vc - } + static let window = SceneType(storyboard: Placeholder.self, identifier: "Window") } } enum StoryboardSegue { - enum Message: String, StoryboardSegueType { + enum Message: String, SegueType { case embed = "Embed" case modal = "Modal" case popover = "Popover" diff --git a/Tests/TemplatesTests/StoryboardsMacOSTests.swift b/Tests/TemplatesTests/StoryboardsMacOSTests.swift index 41788ed..06d6f75 100644 --- a/Tests/TemplatesTests/StoryboardsMacOSTests.swift +++ b/Tests/TemplatesTests/StoryboardsMacOSTests.swift @@ -6,7 +6,6 @@ import StencilSwiftKit import XCTest -import StencilSwiftKit class StoryboardsMacOSTests: XCTestCase { enum Contexts { @@ -17,47 +16,41 @@ class StoryboardsMacOSTests: XCTestCase { let variations: VariationGenerator = { name, context in guard name == "all" else { return [(context: context, suffix: "")] } - do { - return [ - (context: context, - suffix: ""), - (context: try StencilContext.enrich(context: context, - parameters: ["sceneEnumName=XCTStoryboardsScene", - "segueEnumName=XCTStoryboardsSegue"]), - suffix: "-customname"), - (context: try StencilContext.enrich(context: context, - parameters: [], - environment: ["PRODUCT_MODULE_NAME": "Test"]), - suffix: ""), - (context: try StencilContext.enrich(context: context, - parameters: [], - environment: ["PRODUCT_MODULE_NAME": "FadeSegue"]), - suffix: "-ignore-module"), - (context: try StencilContext.enrich(context: context, - parameters: ["module=Test"]), - suffix: ""), - (context: try StencilContext.enrich(context: context, - parameters: ["module=FadeSegue"]), - suffix: "-ignore-module") - ] - } catch { - fatalError("Unable to create context variations") - } + return [ + (context: context, + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["sceneEnumName=XCTStoryboardsScene", + "segueEnumName=XCTStoryboardsSegue"]), + suffix: "-customname"), + (context: try StencilContext.enrich(context: context, + parameters: [], + environment: ["PRODUCT_MODULE_NAME": "Test"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: [], + environment: ["PRODUCT_MODULE_NAME": "FadeSegue"]), + suffix: "-ignore-module"), + (context: try StencilContext.enrich(context: context, + parameters: ["module=Test"]), + suffix: ""), + (context: try StencilContext.enrich(context: context, + parameters: ["module=FadeSegue"]), + suffix: "-ignore-module") + ] } func testSwift2() { - test(template: "macOS-swift2", + test(template: "swift2", contextNames: Contexts.all, - outputPrefix: "swift2", directory: .storyboards, resourceDirectory: .storyboardsMacOS, contextVariations: variations) } func testSwift3() { - test(template: "macOS-swift3", + test(template: "swift3", contextNames: Contexts.all, - outputPrefix: "swift3", directory: .storyboards, resourceDirectory: .storyboardsMacOS, contextVariations: variations) diff --git a/Tests/TemplatesTests/TestsHelper.swift b/Tests/TemplatesTests/TestsHelper.swift index a727ad9..f2483c6 100644 --- a/Tests/TemplatesTests/TestsHelper.swift +++ b/Tests/TemplatesTests/TestsHelper.swift @@ -141,15 +141,12 @@ extension XCTestCase { - Parameter template: The name of the template (without the `stencil` extension) - Parameter contextNames: A list of context names (without the `plist` extension) - - Parameter outputPrefix: Prefix for the output files, becomes "{outputPrefix}-context-{contextName}.swift". - Defaults to template name. - Parameter directory: The directory to look for files in (correspons to de command) - - Parameter resourceDirectory: The directory to look for files in (corresponds to de command) + - Parameter resourceDirectory: The directory to look for files in (corresponds to the command) - Parameter contextVariations: Optional closure to generate context variations. */ func test(template templateName: String, contextNames: [String], - outputPrefix: String? = nil, directory: Fixtures.Directory, resourceDirectory: Fixtures.Directory? = nil, file: StaticString = #file, @@ -161,7 +158,6 @@ extension XCTestCase { // default values let contextVariations = contextVariations ?? { [(context: $1, suffix: "")] } - let prefix = outputPrefix ?? templateName let resourceDir = resourceDirectory ?? directory for contextName in contextNames { @@ -174,7 +170,7 @@ extension XCTestCase { } for (index, (context: context, suffix: suffix)) in variations.enumerated() { - let outputFile = "\(prefix)-context-\(contextName)\(suffix).swift" + let outputFile = "\(templateName)-context-\(contextName)\(suffix).swift" if variations.count > 1 { print(" - Variation #\(index)... (expecting: \(outputFile))") } guard let result = try? template.render(context) else { fatalError("Unable to render template") diff --git a/templates/storyboards/macOS-swift2.stencil b/templates/storyboards/macOS-swift2.stencil deleted file mode 100644 index 19745bb..0000000 --- a/templates/storyboards/macOS-swift2.stencil +++ /dev/null @@ -1,109 +0,0 @@ -// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen - -{% if storyboards %} -// swiftlint:disable sorted_imports -{% macro className scene %}{% filter removeNewlines %} - {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} - {{scene.customClass}} - {% else %} - NS{{scene.baseType}} - {% endif %} -{% endfilter %}{% endmacro %} -import Cocoa -import Foundation -{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %} -import {{module}} -{% endfor %} - -// swiftlint:disable file_length - -{# This first part of the code is static, same every time whatever Storyboard you have #} -protocol StoryboardSceneType { - static var storyboardName: String { get } -} - -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { - return NSStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) - } - - static func initialController() -> AnyObject { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return controller - } -} - -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> AnyObject { - return Self.storyboard().instantiateControllerWithIdentifier(self.rawValue) - } - static func controller(identifier: Self) -> AnyObject { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } - -extension NSWindowController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) - } -} - -extension NSViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) - } -} - -{# This is where the generation begins, this code depends on what you have in your Storyboards #} -// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name -{% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} -enum {{sceneEnumName}} { - {% for storyboard in storyboards %} - {% set storyboardName %}{{storyboard.name|swiftIdentifier|escapeReservedKeywords}}{% endset %} - {% if storyboard.scenes %} - enum {{storyboardName}}: String, StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - {% for scene in storyboard.scenes %} - {% set sceneID %}{{scene.identifier|swiftIdentifier}}{% endset %} - - case {{sceneID}}Scene = "{{scene.identifier}}" - {% set sceneClass %}{% call className scene %}{% endset %} - static func instantiate{{sceneID|snakeToCamelCase}}() -> {{sceneClass}} { - guard let vc = {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.controller() as? {{sceneClass}} - else { - fatalError("ViewController '{{scene.identifier}}' is not of the expected class {{sceneClass}}.") - } - return vc - } - {% endfor %} - } - {% else %} - enum {{storyboardName}}: StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - } - {% endif %} - {% endfor %} -} - -enum {{param.segueEnumName|default:"StoryboardSegue"}} { - {% for storyboard in storyboards where storyboard.segues %} - enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, StoryboardSegueType { - {% for segue in storyboard.segues %} - {% set segueID %}{{segue.identifier|swiftIdentifier}}{% endset %} - case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %} - {% endfor %} - } - {% endfor %} -} -// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name - -private final class BundleToken {} -{% else %} -// No storyboard found -{% endif %} diff --git a/templates/storyboards/macOS-swift3.stencil b/templates/storyboards/macOS-swift3.stencil deleted file mode 100644 index 9f1ccd6..0000000 --- a/templates/storyboards/macOS-swift3.stencil +++ /dev/null @@ -1,109 +0,0 @@ -// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen - -{% if storyboards %} -// swiftlint:disable sorted_imports -{% macro className scene %}{% filter removeNewlines %} - {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} - {{scene.customClass}} - {% else %} - NS{{scene.baseType}} - {% endif %} -{% endfilter %}{% endmacro %} -import Cocoa -import Foundation -{% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %} -import {{module}} -{% endfor %} - -// swiftlint:disable file_length - -{# This first part of the code is static, same every time whatever Storyboard you have #} -protocol StoryboardSceneType { - static var storyboardName: String { get } -} - -extension StoryboardSceneType { - static func storyboard() -> NSStoryboard { - return NSStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) - } - - static func initialController() -> Any { - guard let controller = storyboard().instantiateInitialController() - else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return controller - } -} - -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func controller() -> Any { - return Self.storyboard().instantiateController(withIdentifier: self.rawValue) - } - static func controller(identifier: Self) -> Any { - return identifier.controller() - } -} - -protocol StoryboardSegueType: RawRepresentable { } - -extension NSWindowController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) - } -} - -extension NSViewController { - func performSegue(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) - } -} - -{# This is where the generation begins, this code depends on what you have in your Storyboards #} -// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name -{% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} -enum {{sceneEnumName}} { - {% for storyboard in storyboards %} - {% set storyboardName %}{{storyboard.name|swiftIdentifier|escapeReservedKeywords}}{% endset %} - {% if storyboard.scenes %} - enum {{storyboardName}}: String, StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - {% for scene in storyboard.scenes %} - {% set sceneID %}{{scene.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord}}{% endset %} - - case {{sceneID}}Scene = "{{scene.identifier}}" - {% set sceneClass %}{% call className scene %}{% endset %} - static func instantiate{{sceneID||snakeToCamelCase}}() -> {{sceneClass}} { - guard let vc = {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.controller() as? {{sceneClass}} - else { - fatalError("ViewController '{{scene.identifier}}' is not of the expected class {{sceneClass}}.") - } - return vc - } - {% endfor %} - } - {% else %} - enum {{storyboardName}}: StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - } - {% endif %} - {% endfor %} -} - -enum {{param.segueEnumName|default:"StoryboardSegue"}} { - {% for storyboard in storyboards where storyboard.segues %} - enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, StoryboardSegueType { - {% for segue in storyboard.segues %} - {% set segueID %}{{segue.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord}}{% endset %} - case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %} - {% endfor %} - } - {% endfor %} -} -// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name - -private final class BundleToken {} -{% else %} -// No storyboard found -{% endif %} diff --git a/templates/storyboards/swift2.stencil b/templates/storyboards/swift2.stencil index 8c877e5..328ce8f 100644 --- a/templates/storyboards/swift2.stencil +++ b/templates/storyboards/swift2.stencil @@ -1,17 +1,12 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen -{% if storyboards %} +{% if platform and storyboards %} +{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %} +{% set prefix %}{% if isAppKit %}NS{% else %}UI{% endif %}{% endset %} +{% set controller %}{% if isAppKit %}Controller{% else %}ViewController{% endif %}{% endset %} // swiftlint:disable sorted_imports -{% macro className scene %}{% filter removeNewlines %} - {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} - {{scene.customClass}} - {% else %} - UI{{scene.baseType}} - {% endif %} -{% endfilter %}{% endmacro %} import Foundation -import UIKit +import {% if isAppKit %}Cocoa{% else %}UIKit{% endif %} {% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %} import {{module}} {% endfor %} @@ -19,100 +14,81 @@ import {{module}} // swiftlint:disable file_length {# This first part of the code is static, same every time whatever Storyboard you have #} -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { - return UIStoryboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) +extension StoryboardType { + static var storyboard: {{prefix}}Storyboard { + return {{prefix}}Storyboard(name: self.storyboardName, bundle: NSBundle(forClass: BundleToken.self)) } +} - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiate{{controller}}WithIdentifier(identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewControllerWithIdentifier(self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitial{{controller}}() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } -extension UIViewController { - func performSegue(segue: S, sender: AnyObject? = nil) { - performSegueWithIdentifier(segue.rawValue, sender: sender) +extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif %} { + func performSegue(segue: S, sender: AnyObject? = nil) { + performSegueWithIdentifier{% if isAppKit %}?{% endif %}(segue.rawValue, sender: sender) } } {# This is where the generation begins, this code depends on what you have in your Storyboards #} // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name {% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} +{% macro className scene %}{% filter removeNewlines %} + {% if scene.customClass %} + {% if scene.customModule %}{{scene.customModule}}.{% endif %} + {{scene.customClass}} + {% else %} + {{prefix}}{{scene.baseType}} + {% endif %} +{% endfilter %}{% endmacro %} enum {{sceneEnumName}} { {% for storyboard in storyboards %} {% set storyboardName %}{{storyboard.name|swiftIdentifier|escapeReservedKeywords}}{% endset %} - {% if storyboard.scenes %} - enum {{storyboardName}}: String, StoryboardSceneType { + enum {{storyboardName}}: StoryboardType { static let storyboardName = "{{storyboard.name}}" - {% if storyboard.initialScene and storyboard.initialScene.baseType != "ViewController" %} - {% set initialSceneClass %}{% call className storyboard.initialScene %}{% endset %} + {% if storyboard.initialScene %} - static func initialViewController() -> {{initialSceneClass}} { - guard let vc = storyboard().instantiateInitialViewController() as? {{initialSceneClass}} else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + {% set sceneClass %}{% call className storyboard.initialScene %}{% endset %} + static let initialScene = InitialSceneType<{{sceneClass}}>({{storyboardName}}.self) {% endif %} {% for scene in storyboard.scenes %} - {% set sceneID %}{{scene.identifier|swiftIdentifier}}{% endset %} - case {{sceneID}}Scene = "{{scene.identifier}}" - {% if scene.baseType != "ViewController" %} + {% set sceneID %}{{scene.identifier|swiftIdentifier|escapeReservedKeywords}}{% endset %} {% set sceneClass %}{% call className scene %}{% endset %} - static func instantiate{{sceneID|snakeToCamelCase}}() -> {{sceneClass}} { - guard let vc = {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.viewController() as? {{sceneClass}} - else { - fatalError("ViewController '{{scene.identifier}}' is not of the expected class {{sceneClass}}.") - } - return vc - } - {% else %} - static func instantiate{{sceneID|snakeToCamelCase}}() -> UIViewController { - return {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.viewController() - } - {% endif %} + static let {{sceneID}} = SceneType<{{sceneClass}}>({{storyboardName}}.self, identifier: "{{scene.identifier}}") {% endfor %} } - {% else %} - enum {{storyboardName}}: StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - {% if storyboard.initialScene and storyboard.initialScene.baseType != "ViewController" %} - {% set initialSceneClass %}{% call className storyboard.initialScene %}{% endset %} - - static func initialViewController() -> {{initialSceneClass}} { - guard let vc = storyboard().instantiateInitialViewController() as? {{initialSceneClass}} else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } - {% endif %} - } - {% endif %} {% endfor %} } enum {{param.segueEnumName|default:"StoryboardSegue"}} { {% for storyboard in storyboards where storyboard.segues %} - enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, StoryboardSegueType { + enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, SegueType { {% for segue in storyboard.segues %} {% set segueID %}{{segue.identifier|swiftIdentifier}}{% endset %} case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %} @@ -123,6 +99,8 @@ enum {{param.segueEnumName|default:"StoryboardSegue"}} { // swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name private final class BundleToken {} +{% elif storyboards %} +// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately {% else %} // No storyboard found {% endif %} diff --git a/templates/storyboards/swift3.stencil b/templates/storyboards/swift3.stencil index 9abb104..6288d7f 100644 --- a/templates/storyboards/swift3.stencil +++ b/templates/storyboards/swift3.stencil @@ -1,17 +1,12 @@ // Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen -{% if storyboards %} +{% if platform and storyboards %} +{% set isAppKit %}{% if platform == "macOS" %}true{% endif %}{% endset %} +{% set prefix %}{% if isAppKit %}NS{% else %}UI{% endif %}{% endset %} +{% set controller %}{% if isAppKit %}Controller{% else %}ViewController{% endif %}{% endset %} // swiftlint:disable sorted_imports -{% macro className scene %}{% filter removeNewlines %} - {% if scene.customClass %} - {% if scene.customModule %}{{scene.customModule}}.{% endif %} - {{scene.customClass}} - {% else %} - UI{{scene.baseType}} - {% endif %} -{% endfilter %}{% endmacro %} import Foundation -import UIKit +import {% if isAppKit %}Cocoa{% else %}UIKit{% endif %} {% for module in modules where module != env.PRODUCT_MODULE_NAME and module != param.module %} import {{module}} {% endfor %} @@ -19,100 +14,81 @@ import {{module}} // swiftlint:disable file_length {# This first part of the code is static, same every time whatever Storyboard you have #} -protocol StoryboardSceneType { +protocol StoryboardType { static var storyboardName: String { get } } -extension StoryboardSceneType { - static func storyboard() -> UIStoryboard { - return UIStoryboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) +extension StoryboardType { + static var storyboard: {{prefix}}Storyboard { + return {{prefix}}Storyboard(name: self.storyboardName, bundle: Bundle(for: BundleToken.self)) } +} - static func initialViewController() -> UIViewController { - guard let vc = storyboard().instantiateInitialViewController() else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") +struct SceneType { + let storyboard: StoryboardType.Type + let identifier: String + + var controller: T { + guard let controller = storyboard.storyboard.instantiate{{controller}}(withIdentifier: identifier) as? T else { + fatalError("Controller '\(identifier)' is not of the expected class \(T.self).") } - return vc + return controller } } -extension StoryboardSceneType where Self: RawRepresentable, Self.RawValue == String { - func viewController() -> UIViewController { - return Self.storyboard().instantiateViewController(withIdentifier: self.rawValue) - } - static func viewController(identifier: Self) -> UIViewController { - return identifier.viewController() +struct InitialSceneType { + let storyboard: StoryboardType.Type + + var controller: T { + guard let controller = storyboard.storyboard.instantiateInitial{{controller}}() as? T else { + fatalError("Controller is not of the expected class \(T.self).") + } + return controller } } -protocol StoryboardSegueType: RawRepresentable { } +protocol SegueType: RawRepresentable { } -extension UIViewController { - func perform(segue: S, sender: Any? = nil) where S.RawValue == String { - performSegue(withIdentifier: segue.rawValue, sender: sender) +extension {% if isAppKit %}NSSeguePerforming{% else %}UIViewController{% endif %} { + func perform(segue: S, sender: Any? = nil) where S.RawValue == String { + performSegue{% if isAppKit %}?{% endif %}(withIdentifier: segue.rawValue, sender: sender) } } {# This is where the generation begins, this code depends on what you have in your Storyboards #} // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name {% set sceneEnumName %}{{param.sceneEnumName|default:"StoryboardScene"}}{% endset %} +{% macro className scene %}{% filter removeNewlines %} + {% if scene.customClass %} + {% if scene.customModule %}{{scene.customModule}}.{% endif %} + {{scene.customClass}} + {% else %} + {{prefix}}{{scene.baseType}} + {% endif %} +{% endfilter %}{% endmacro %} enum {{sceneEnumName}} { {% for storyboard in storyboards %} {% set storyboardName %}{{storyboard.name|swiftIdentifier|escapeReservedKeywords}}{% endset %} - {% if storyboard.scenes %} - enum {{storyboardName}}: String, StoryboardSceneType { + enum {{storyboardName}}: StoryboardType { static let storyboardName = "{{storyboard.name}}" - {% if storyboard.initialScene and storyboard.initialScene.baseType != "ViewController" %} - {% set initialSceneClass %}{% call className storyboard.initialScene %}{% endset %} + {% if storyboard.initialScene %} - static func initialViewController() -> {{initialSceneClass}} { - guard let vc = storyboard().instantiateInitialViewController() as? {{initialSceneClass}} else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } + {% set sceneClass %}{% call className storyboard.initialScene %}{% endset %} + static let initialScene = InitialSceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self) {% endif %} {% for scene in storyboard.scenes %} - {% set sceneID %}{{scene.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord}}{% endset %} - case {{sceneID}}Scene = "{{scene.identifier}}" - {% if scene.baseType != "ViewController" %} + {% set sceneID %}{{scene.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord|escapeReservedKeywords}}{% endset %} {% set sceneClass %}{% call className scene %}{% endset %} - static func instantiate{{sceneID|snakeToCamelCase}}() -> {{sceneClass}} { - guard let vc = {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.viewController() as? {{sceneClass}} - else { - fatalError("ViewController '{{scene.identifier}}' is not of the expected class {{sceneClass}}.") - } - return vc - } - {% else %} - static func instantiate{{sceneID|snakeToCamelCase}}() -> UIViewController { - return {{sceneEnumName}}.{{storyboardName}}.{{sceneID}}Scene.viewController() - } - {% endif %} + static let {{sceneID}} = SceneType<{{sceneClass}}>(storyboard: {{storyboardName}}.self, identifier: "{{scene.identifier}}") {% endfor %} } - {% else %} - enum {{storyboardName}}: StoryboardSceneType { - static let storyboardName = "{{storyboard.name}}" - {% if storyboard.initialScene and storyboard.initialScene.baseType != "ViewController" %} - {% set initialSceneClass %}{% call className storyboard.initialScene %}{% endset %} - - static func initialViewController() -> {{initialSceneClass}} { - guard let vc = storyboard().instantiateInitialViewController() as? {{initialSceneClass}} else { - fatalError("Failed to instantiate initialViewController for \(self.storyboardName)") - } - return vc - } - {% endif %} - } - {% endif %} {% endfor %} } enum {{param.segueEnumName|default:"StoryboardSegue"}} { {% for storyboard in storyboards where storyboard.segues %} - enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, StoryboardSegueType { + enum {{storyboard.name|swiftIdentifier|escapeReservedKeywords}}: String, SegueType { {% for segue in storyboard.segues %} {% set segueID %}{{segue.identifier|swiftIdentifier|snakeToCamelCase|lowerFirstWord}}{% endset %} case {{segueID|escapeReservedKeywords}}{% if segueID != segue.identifier %} = "{{segue.identifier}}"{% endif %} @@ -123,6 +99,8 @@ enum {{param.segueEnumName|default:"StoryboardSegue"}} { // swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name private final class BundleToken {} +{% elif storyboards %} +// Mixed AppKit and UIKit storyboard files found, please invoke swiftgen with these separately {% else %} // No storyboard found {% endif %}