├── .gitignore
├── LICENSE
├── README.md
├── VIPER Coordinators
├── Application Coordinator.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___.swift
├── Coordinator Protocol.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___.swift
├── Interactor.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ ├── ___FILEBASENAME___Interactor.swift
│ ├── ___FILEBASENAME___Models.swift
│ └── ___FILEBASENAME___Protocols.swift
└── Scene.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ ├── UIViewController
│ ├── ___FILEBASENAME___Models.swift
│ ├── ___FILEBASENAME___Presenter.swift
│ ├── ___FILEBASENAME___Protocols.swift
│ ├── ___FILEBASENAME___ViewController.storyboard
│ └── ___FILEBASENAME___ViewController.swift
│ └── UIViewControllerwithCoordinator
│ ├── ___FILEBASENAME___Coordinator.swift
│ ├── ___FILEBASENAME___Models.swift
│ ├── ___FILEBASENAME___Presenter.swift
│ ├── ___FILEBASENAME___Protocols.swift
│ ├── ___FILEBASENAME___ViewController.storyboard
│ └── ___FILEBASENAME___ViewController.swift
└── install.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # Carthage
49 | #
50 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
51 | # Carthage/Checkouts
52 | Carthage/
53 | #Carthage/Build
54 |
55 | # fastlane
56 | #
57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
58 | # screenshots whenever they are needed.
59 | # For more information about the recommended setup visit:
60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
61 |
62 | fastlane/report.xml
63 | fastlane/screenshots
64 |
65 | .DS_Store
66 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Nodes Agency - iOS
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #  VIPER Coordinators Xcode File Template
2 |
3 | An Xcode file template that generates multiple files with boilerplate code required for setting up a scene using VIPER and Coordinators.
4 |
5 | [](https://github.com/nodes-ios/VIPERCoordinatorsXcodeFileTemplate/blob/master/LICENSE)
6 |
7 | ## 📦 Installation
8 |
9 | 1. Clone this repository
10 | 2. `cd` to it in Terminal
11 | 3. Change permissions and run the install script
12 |
13 | ~~~
14 | chmod 755 install.sh && ./install.sh
15 | ~~~
16 |
17 | #### To remove old templates
18 | Go to /Library/Developer/Xcode/Templates/File Templates and delete the ones you don't need anymore.
19 |
20 | ## Usage
21 |
22 | 1. Open your Xcode project
23 | 2. Create a new file (`Cmd + N`)
24 | 3. Notice VIPER Coordinators in the left pane
25 |
26 | ## Known Issues
27 |
28 | Various current and previous issues and how to fix them.
29 |
30 | #### Coordinator Leak
31 | In all versions up to version 1.5.0 (not including) there was a memory leak due to a retain cycle between the presenter and the coordinator.
32 |
33 | This is the entire retain cycle:
34 | `Coordinator` **>** `Navigation Controller` **>** `View Controller` **>** `Presenter` **>** `Coordinator`
35 |
36 | 
37 |
38 | The steps to fix this are as follows:
39 |
40 | 1. Make the `YourCoordinatorInput` protocol a class protocol by appending `: class` to its declaration
41 | 2. Change the coordinator reference in the presetner (the property) to be a weak reference, ie. `weak var coordinator: YourCoordinatorInput?`
42 | 3. Update all code in presenter referencing coordinator with `?` to fix issues with the property now being optional
43 |
44 | To do all steps faster and automatically you can use Xcode's search and replace with regular expressions as follows:
45 |
46 | **Step 1**
47 | Search field: `protocol ([\w]*)CoordinatorInput \{`
48 | Replace field: `protocol $1CoordinatorInput: class \{`
49 |
50 | **Step 2**
51 | Search field: `let coordinator: ([\w]*)CoordinatorInput`
52 | Replace field: `weak var coordinator: $1CoordinatorInput?`
53 |
54 | **Step 3** (experimental, might need tweaks)
55 | Search field: `([\n]+[\s]*coordinator)\.(?!start)`
56 | Replace field: `$1?\.`
57 |
58 | ## 💥 How we use!
59 |
60 | Check it out [HERE](https://github.com/nodes-ios/Playbook/blob/master/ViperArchitecture.md) to see how we use this awesome pattern!
61 |
62 | ## 👥 Credits
63 | Made with ❤️ at [Nodes](http://nodesagency.com).
64 |
65 | ## 📄 License
66 | **VIPER Coordinators Xcode File Template** is available under the MIT license. See the [LICENSE](https://github.com/nodes-ios/VIPERCoordinatorsXcodeFileTemplate/blob/master/LICENSE) file for more info.
67 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Application Coordinator.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Application Coordinator.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Application Coordinator.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Application Coordinator.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Application Coordinator.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kind
6 | Xcode.IDEFoundation.TextSubstitutionFileTemplateKind
7 | Description
8 | Main application coordinator, designated to be used from within your app delegate.
9 | Summary
10 | Main application coordinator, designated to be used from within your app delegate
11 | SortOrder
12 | 30
13 | AllowedTypes
14 |
15 | public.swift-source
16 |
17 | DefaultCompletionName
18 | AppCoordinator
19 | MainTemplateFile
20 | ___FILEBASENAME___.swift
21 |
22 |
23 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Application Coordinator.xctemplate/___FILEBASENAME___.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | //___COPYRIGHT___
7 | //
8 |
9 | import UIKit
10 |
11 | class ___FILEBASENAMEASIDENTIFIER___: Coordinator {
12 |
13 | let window: UIWindow
14 | var children: [Coordinator] = []
15 |
16 | init(window: UIWindow) {
17 | self.window = window
18 | }
19 |
20 | func start() {
21 | // Perform initial application seutp.
22 | setupAfterLaunch()
23 |
24 | // Start your first flow here. For example, this is the
25 | // ideal place for deciding if you should show login or main flows.
26 | showMain()
27 |
28 | // Finally make the window key and visible.
29 | window.makeKeyAndVisible()
30 | }
31 |
32 | // MARK: - Flows -
33 |
34 | func showMain() {
35 | // Create your child coordinator here, add it as a child and start it.
36 | // Make sure you set the root view controller of the window.
37 | }
38 |
39 | // MARK: - Additional Setup -
40 |
41 | func setupAfterLaunch() {
42 | // Perform initial app setup after launch like analytics, integrations and more.
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Coordinator Protocol.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Coordinator Protocol.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Coordinator Protocol.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Coordinator Protocol.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Coordinator Protocol.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kind
6 | Xcode.IDEFoundation.TextSubstitutionFileTemplateKind
7 | Description
8 | A default Coordinator protocol implementation.
9 | Summary
10 | A default Coordinator protocol implementation
11 | SortOrder
12 | 30
13 | AllowedTypes
14 |
15 | public.swift-source
16 |
17 | DefaultCompletionName
18 | Coordinator
19 | MainTemplateFile
20 | ___FILEBASENAME___.swift
21 |
22 |
23 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Coordinator Protocol.xctemplate/___FILEBASENAME___.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | //___COPYRIGHT___
7 | //
8 |
9 | import UIKit
10 |
11 | protocol ___FILEBASENAMEASIDENTIFIER___: AnyObject {
12 | var children: [Coordinator] { get set }
13 | func start()
14 | }
15 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Interactor.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Interactor.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | Example
7 | Description
8 | This generates a new interactor. It consists of the interactr, protocols and models.
9 | Kind
10 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
11 | Options
12 |
13 |
14 | Description
15 | The name of the interactor to create
16 | Identifier
17 | sceneName
18 | Name
19 | New Interactor Name:
20 | NotPersisted
21 |
22 | Required
23 |
24 | Type
25 | text
26 |
27 |
28 | Default
29 | ___VARIABLE_sceneName:identifier___
30 | Identifier
31 | productName
32 | Type
33 | static
34 |
35 |
36 | Default
37 | ___VARIABLE_sceneName:identifier___Protocols
38 | Description
39 | The protocols file name
40 | Identifier
41 | protocolsName
42 | Name
43 | Protocols Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Default
51 | ___VARIABLE_sceneName:identifier___Interactor
52 | Description
53 | The interactor name
54 | Identifier
55 | interactorName
56 | Name
57 | Interactor Name:
58 | Required
59 |
60 | Type
61 | static
62 |
63 |
64 | Default
65 | ___VARIABLE_sceneName:identifier___Models
66 | Description
67 | The model file name
68 | Identifier
69 | modelFileName
70 | Name
71 | Models Name:
72 | Required
73 |
74 | Type
75 | static
76 |
77 |
78 | SortOrder
79 | 9
80 | Summary
81 | This generates a new interactor.
82 | AllowedTypes
83 |
84 | public.swift-source
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/___FILEBASENAME___Interactor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class ___VARIABLE_sceneName___Interactor {
12 | // MARK: - Properties
13 | weak var output: ___VARIABLE_sceneName___InteractorOutput?
14 |
15 | // MARK: - Init
16 | init() {
17 |
18 | // Log init
19 | }
20 |
21 | deinit {
22 | // Log deinit
23 | }
24 | }
25 |
26 | // MARK: - Business Logic -
27 |
28 | // PRESENTER -> INTERACTOR
29 | extension ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___InteractorInput {
30 | }
31 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/___FILEBASENAME___Models.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum ___VARIABLE_sceneName___ {
12 | enum Request { }
13 | enum Response { }
14 | }
15 |
16 | extension ___VARIABLE_sceneName___.Request {
17 |
18 | }
19 |
20 | extension ___VARIABLE_sceneName___.Response {
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Interactor.xctemplate/___FILEBASENAME___Protocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | // PRESENTER -> INTERACTOR
12 | protocol ___VARIABLE_sceneName___InteractorInput {
13 | // func perform(_ request: ___VARIABLE_sceneName___.Request.Work)
14 | }
15 |
16 | // INTERACTOR -> PRESENTER (indirect)
17 | protocol ___VARIABLE_sceneName___InteractorOutput: AnyObject {
18 | // func present(_ response: ___VARIABLE_sceneName___.Response.Work)
19 | }
20 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Scene.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ml-archive/VIPERCoordinatorsXcodeFileTemplate/476461dafabfef2b35d72e514a31eb182dbdea11/VIPER Coordinators/Scene.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new scene using clean architecture and coordinators. It consists of the view controller, presenter and optionally a coordinator.
9 | Kind
10 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
11 | Options
12 |
13 |
14 | Description
15 | The name of the scene to create
16 | Identifier
17 | sceneName
18 | Name
19 | New Scene Name:
20 | NotPersisted
21 |
22 | Required
23 |
24 | Type
25 | text
26 |
27 |
28 | Default
29 | ___VARIABLE_sceneName:identifier___
30 | Identifier
31 | productName
32 | Type
33 | static
34 |
35 |
36 | Default
37 | ___VARIABLE_sceneName:identifier___ViewController
38 | Description
39 | The view controller name
40 | Identifier
41 | viewControllerName
42 | Name
43 | View Controller Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Default
51 | ___VARIABLE_sceneName:identifier___Presenter
52 | Description
53 | The presenter name
54 | Identifier
55 | presenterName
56 | Name
57 | Presenter Name:
58 | Required
59 |
60 | Type
61 | static
62 |
63 |
64 | Default
65 | ___VARIABLE_sceneName:identifier___Coordinator
66 | Description
67 | The coordinator name
68 | Identifier
69 | coordinatorName
70 | Name
71 | Coordinator Name:
72 | Required
73 |
74 | Type
75 | static
76 |
77 |
78 | Default
79 | ___VARIABLE_sceneName:identifier___Models
80 | Description
81 | The model file name
82 | Identifier
83 | modelFileName
84 | Name
85 | Model File Name:
86 | Required
87 |
88 | Type
89 | static
90 |
91 |
92 | Default
93 | UIViewController
94 | Description
95 | What view controller class to subclass for the new scene
96 | FallbackHeader
97 | #import <UIKit/UIKit.h>
98 | Identifier
99 | viewControllerSubclass
100 | Name
101 | Subclass of:
102 | NotPersisted
103 |
104 | Required
105 | YES
106 | Type
107 | class
108 | Values
109 |
110 | UIViewController
111 |
112 |
113 |
114 | Default
115 |
116 | Description
117 | Wheter to create a Coordinator for this scene
118 | Identifier
119 | withCoordinator
120 | Name
121 | Also create a Coordinator
122 | Type
123 | checkbox
124 |
125 |
126 | Platforms
127 |
128 | com.apple.platform.iphoneos
129 | com.apple.platform.tvos
130 |
131 | SortOrder
132 | 9
133 | Summary
134 | This generates a new scene using clean architecture enhanced with coordinators.
135 |
136 |
137 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewController/___FILEBASENAME___Models.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum ___VARIABLE_sceneName___ {
12 | enum DisplayData { }
13 |
14 | enum Action {
15 |
16 | }
17 |
18 | enum Route {
19 |
20 | }
21 | }
22 |
23 | extension ___VARIABLE_sceneName___.DisplayData {
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewController/___FILEBASENAME___Presenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class ___VARIABLE_sceneName___Presenter {
12 | // MARK: - Properties
13 | weak var coordinator: ___VARIABLE_sceneName___CoordinatorInput?
14 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
15 |
16 | // MARK: - Init
17 | init(coordinator: ___VARIABLE_sceneName___CoordinatorInput) {
18 | self.coordinator = coordinator
19 | }
20 | }
21 |
22 | // MARK: - User Events -
23 | // -----------------------------------------------
24 | // View input will be handled below.
25 |
26 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
27 | func viewCreated() {
28 |
29 | }
30 |
31 | func handle(_ action: ___VARIABLE_sceneName___.Action) {
32 |
33 | }
34 | }
35 |
36 | // MARK: - Presentation Logic -
37 | // -----------------------------------------------
38 | // Interactor output implementation will go below.
39 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewController/___FILEBASENAME___Protocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | // ======== Coordinator ======== //
13 |
14 | // PRESENTER -> COORDINATOR
15 | protocol ___VARIABLE_sceneName___CoordinatorInput: AnyObject {
16 | func navigate(to route: ___VARIABLE_sceneName___.Route)
17 | }
18 |
19 | // ======== Presenter ======== //
20 |
21 | // VIEW -> PRESENTER
22 | protocol ___VARIABLE_sceneName___PresenterInput {
23 | func viewCreated()
24 | func handle(_ action: ___VARIABLE_sceneName___.Action)
25 | }
26 |
27 | // PRESENTER -> VIEW
28 | protocol ___VARIABLE_sceneName___PresenterOutput: AnyObject {
29 | // func display(_ displayModel: ___VARIABLE_sceneName___.DisplayData.Work)
30 | }
31 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewController/___FILEBASENAME___ViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewController/___FILEBASENAME___ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ___VARIABLE_sceneName___ViewController: UIViewController {
12 | // MARK: - Outlets
13 |
14 | // MARK: - Properties
15 | private var presenter: ___VARIABLE_sceneName___PresenterInput!
16 |
17 | // MARK: - Init
18 | class func instantiate(with presenter: ___VARIABLE_sceneName___PresenterInput) -> ___VARIABLE_sceneName___ViewController {
19 | let name = "\(___VARIABLE_sceneName___ViewController.self)"
20 | let storyboard = UIStoryboard(name: name, bundle: nil)
21 |
22 | guard let vc = storyboard.instantiateViewController(withIdentifier: name) as? ___VARIABLE_sceneName___ViewController else {
23 | preconditionFailure("Unable to instantiate a ___VARIABLE_sceneName___ViewController with the name \(name)")
24 | }
25 |
26 | vc.presenter = presenter
27 |
28 | return vc
29 | }
30 |
31 | // MARK: - View Lifecycle -
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 | presenter.viewCreated()
36 | }
37 |
38 | // MARK: - Callbacks -
39 |
40 | }
41 |
42 | // MARK: - Display Logic -
43 |
44 | // PRESENTER -> VIEW
45 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___Coordinator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class ___VARIABLE_sceneName___Coordinator: Coordinator {
13 | // MARK: - Properties
14 | let navigationController: UINavigationController
15 | // NOTE: This array is used to retain child coordinators. Don't forget to
16 | // remove them when the coordinator is done.
17 | var children: [Coordinator] = []
18 | // weak var delegate: ___VARIABLE_sceneName___CoordinatorDelegate?
19 |
20 | // MARK: - Init
21 | init(navigationController: UINavigationController) {
22 | self.navigationController = navigationController
23 | }
24 |
25 | func start() {
26 | let presenter = ___VARIABLE_sceneName___Presenter(coordinator: self)
27 | let vc = ___VARIABLE_sceneName___ViewController.instantiate(with: presenter)
28 |
29 | presenter.output = vc
30 |
31 | // FIXME: Display as you need
32 | // navigationController.setViewControllers([vc], animated: false)
33 | }
34 | }
35 | // MARK: - Navigation Callbacks
36 | // PRESENTER -> COORDINATOR
37 | extension ___VARIABLE_sceneName___Coordinator: ___VARIABLE_sceneName___CoordinatorInput {
38 | func navigate(to route: ___VARIABLE_sceneName___.Route) {
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___Models.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum ___VARIABLE_sceneName___ {
12 | enum DisplayData { }
13 |
14 | enum Action {
15 |
16 | }
17 |
18 | enum Route {
19 |
20 | }
21 | }
22 |
23 | extension ___VARIABLE_sceneName___.DisplayData {
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___Presenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class ___VARIABLE_sceneName___Presenter {
12 | // MARK: - Properties
13 | weak var coordinator: ___VARIABLE_sceneName___CoordinatorInput?
14 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
15 |
16 | // MARK: - Init
17 | init(coordinator: ___VARIABLE_sceneName___CoordinatorInput) {
18 | self.coordinator = coordinator
19 | }
20 | }
21 |
22 | // MARK: - User Events -
23 | // -----------------------------------------------
24 | // View input will be handled below.
25 |
26 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
27 | func viewCreated() {
28 |
29 | }
30 |
31 | func handle(_ action: ___VARIABLE_sceneName___.Action) {
32 |
33 | }
34 | }
35 |
36 | // MARK: - Presentation Logic -
37 | // -----------------------------------------------
38 | // Interactor output implementation will go below.
39 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___Protocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | // ======== Coordinator ======== //
13 |
14 | //protocol ___VARIABLE_sceneName___CoordinatorDelegate: AnyObject {
15 | // func coordinator(_ coordinator: Coordinator, finishedWithSuccess success: Bool)
16 | //}
17 |
18 | // PRESENTER -> COORDINATOR
19 | protocol ___VARIABLE_sceneName___CoordinatorInput: AnyObject {
20 | func navigate(to route: ___VARIABLE_sceneName___.Route)
21 | }
22 |
23 | // ======== Presenter ======== //
24 |
25 | // VIEW -> PRESENTER
26 | protocol ___VARIABLE_sceneName___PresenterInput {
27 | func viewCreated()
28 | func handle(_ action: ___VARIABLE_sceneName___.Action)
29 | }
30 |
31 | // PRESENTER -> VIEW
32 | protocol ___VARIABLE_sceneName___PresenterOutput: AnyObject {
33 | // func display(_ displayModel: ___VARIABLE_sceneName___.DisplayData.Work)
34 | }
35 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___ViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/VIPER Coordinators/Scene.xctemplate/UIViewControllerwithCoordinator/___FILEBASENAME___ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ___VARIABLE_sceneName___ViewController: UIViewController {
12 | // MARK: - Outlets
13 |
14 | // MARK: - Properties
15 | private var presenter: ___VARIABLE_sceneName___PresenterInput!
16 |
17 | // MARK: - Init
18 | class func instantiate(with presenter: ___VARIABLE_sceneName___PresenterInput) -> ___VARIABLE_sceneName___ViewController {
19 | let name = "\(___VARIABLE_sceneName___ViewController.self)"
20 | let storyboard = UIStoryboard(name: name, bundle: nil)
21 |
22 | guard let vc = storyboard.instantiateViewController(withIdentifier: name) as? ___VARIABLE_sceneName___ViewController else {
23 | preconditionFailure("Unable to instantiate a ___VARIABLE_sceneName___ViewController with the name \(name)")
24 | }
25 |
26 | vc.presenter = presenter
27 |
28 | return vc
29 | }
30 |
31 | // MARK: - View Lifecycle -
32 |
33 | override func viewDidLoad() {
34 | super.viewDidLoad()
35 | presenter.viewCreated()
36 | }
37 |
38 | // MARK: - Callbacks -
39 |
40 | }
41 |
42 | // MARK: - Display Logic -
43 |
44 | // PRESENTER -> VIEW
45 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | BASE_XCODE_DIR="${HOME}/Library/Developer/Xcode"
4 | TEMPLATES_XCODE_DIR="${BASE_XCODE_DIR}/Templates"
5 | FILE_TEMPLATES_XCODE_DIR="${TEMPLATES_XCODE_DIR}/File Templates"
6 | TEMPLATES_FOLDER_NAME="VIPER Coordinators"
7 |
8 | echo "Starting installation of VIPER Coordinators templates."
9 |
10 | # Check if templates dir exists
11 | if [ ! -d "${TEMPLATES_XCODE_DIR}" ]; then
12 | echo "Creating Templates directory, because it didn't exist."
13 | mkdir "${TEMPLATES_XCODE_DIR}"
14 | fi
15 |
16 | # Check if file templates dir exists
17 | if [ ! -d "${FILE_TEMPLATES_XCODE_DIR}" ]; then
18 | echo "Creating File Templates directory, because it didn't exist."
19 | mkdir "${FILE_TEMPLATES_XCODE_DIR}"
20 | fi
21 |
22 | # Check if templates exist
23 | if [ -d "${FILE_TEMPLATES_XCODE_DIR}/${TEMPLATES_FOLDER_NAME}" ]; then
24 | echo "Deleting previous ${TEMPLATES_FOLDER_NAME} directory."
25 | rm -rf "${FILE_TEMPLATES_XCODE_DIR}/${TEMPLATES_FOLDER_NAME}"
26 | fi
27 |
28 | # Copy the files
29 | echo "Copying template files."
30 | cp -r "${TEMPLATES_FOLDER_NAME}" "${FILE_TEMPLATES_XCODE_DIR}/"
31 | echo "VIPER Coordinators templates installation done."
32 |
--------------------------------------------------------------------------------