├── Clean Swift
├── Interactor.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Interactor.swift
├── Models.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Models.swift
├── Presenter.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Presenter.swift
├── Router.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Router.swift
├── Scene.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ ├── UICollectionViewController
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ ├── ___FILEBASENAME___ViewController.swift
│ │ └── ___FILEBASENAME___Worker.swift
│ ├── UITableViewController
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ ├── ___FILEBASENAME___ViewController.swift
│ │ └── ___FILEBASENAME___Worker.swift
│ └── UIViewController
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ ├── ___FILEBASENAME___ViewController.swift
│ │ └── ___FILEBASENAME___Worker.swift
├── Unit Tests.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ ├── ___FILEBASENAME___InteractorTests.swift
│ ├── ___FILEBASENAME___PresenterTests.swift
│ ├── ___FILEBASENAME___ViewControllerTests.swift
│ └── ___FILEBASENAME___WorkerTests.swift
├── View Controller.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ ├── UICollectionViewController
│ │ └── ___FILEBASENAME___ViewController.swift
│ ├── UITableViewController
│ │ └── ___FILEBASENAME___ViewController.swift
│ └── UIViewController
│ │ └── ___FILEBASENAME___ViewController.swift
└── Worker.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Worker.swift
├── CleanSwiftExample
├── CleanSwiftExample.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ │ └── yoni.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcuserdata
│ │ └── yoni.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── CleanSwiftExample
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── Model
│ │ ├── Result.swift
│ │ └── User.swift
│ ├── SceneDelegate.swift
│ ├── Screens
│ │ ├── Home
│ │ │ ├── HomeViewController.storyboard
│ │ │ └── HomeViewController.swift
│ │ └── Login
│ │ │ ├── LoginInteractor.swift
│ │ │ ├── LoginModels.swift
│ │ │ ├── LoginPresenter.swift
│ │ │ ├── LoginRouter.swift
│ │ │ ├── LoginViewController.storyboard
│ │ │ └── LoginViewController.swift
│ └── ViewController.swift
├── CleanSwiftExampleTests
│ ├── CleanSwiftExampleTests.swift
│ └── Info.plist
└── CleanSwiftExampleUITests
│ ├── CleanSwiftExampleUITests.swift
│ └── Info.plist
├── LICENSE
└── README.md
/Clean Swift/Interactor.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Interactor.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Interactor.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Interactor.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Interactor.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new interactor using Uncle Bob's clean architecture. Your business logic goes here.
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___Interactor
38 | Description
39 | The interactor name
40 | Identifier
41 | interactorName
42 | Name
43 | Interactor Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Platforms
51 |
52 | com.apple.platform.iphoneos
53 |
54 | SortOrder
55 | 2
56 | Summary
57 | This generates a new interactor using Uncle Bob's clean architecture. Your business logic goes here.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift/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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___BusinessLogic {
16 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request)
17 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request)
18 | }
19 |
20 | protocol ___VARIABLE_sceneName___DataStore {
21 | //var name: String { get set }
22 | }
23 |
24 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___BusinessLogic, ___VARIABLE_sceneName___DataStore {
25 | var presenter: ___VARIABLE_sceneName___PresentationLogic?
26 | var worker: ___VARIABLE_sceneName___Worker?
27 | //var name: String = ""
28 |
29 | // MARK: Do something (and send response to ___VARIABLE_sceneName___Presenter)
30 |
31 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request) {
32 | worker = ___VARIABLE_sceneName___Worker()
33 | worker?.doSomeWork()
34 |
35 | let response = ___VARIABLE_sceneName___.Something.Response()
36 | presenter?.presentSomething(response: response)
37 | }
38 | //
39 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request) {
40 | // worker = ___VARIABLE_sceneName___Worker()
41 | // worker?.doSomeOtherWork()
42 | //
43 | // let response = ___VARIABLE_sceneName___.SomethingElse.Response()
44 | // presenter?.presentSomethingElse(response: response)
45 | // }
46 | }
47 |
--------------------------------------------------------------------------------
/Clean Swift/Models.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Models.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Models.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Models.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Models.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new set of boundary models between the view controller, interactor, presenter, and router using Uncle Bob's clean architecture.
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 | Platforms
37 |
38 | com.apple.platform.iphoneos
39 |
40 | SortOrder
41 | 4
42 | Summary
43 | This generates a new set of boundary models between the view controller, interactor, presenter, and router using Uncle Bob's clean architecture.
44 |
45 |
--------------------------------------------------------------------------------
/Clean Swift/Models.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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | enum ___VARIABLE_sceneName___
16 | {
17 | // MARK: Use cases
18 |
19 | enum Something
20 | {
21 | struct Request
22 | {
23 |
24 | }
25 |
26 | struct Response
27 | {
28 |
29 | }
30 |
31 | struct ViewModel
32 | {
33 |
34 | }
35 | }
36 |
37 | // enum SomethingElse
38 | // {
39 | // struct Request
40 | // {
41 | //
42 | // }
43 | //
44 | // struct Response
45 | // {
46 | //
47 | // }
48 | //
49 | // struct ViewModel
50 | // {
51 | //
52 | // }
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Presenter.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Presenter.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Presenter.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Presenter.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Presenter.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new presenter using Uncle Bob's clean architecture. Your presentation logic goes here.
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___Presenter
38 | Description
39 | The presenter name
40 | Identifier
41 | presenterName
42 | Name
43 | Presenter Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Platforms
51 |
52 | com.apple.platform.iphoneos
53 |
54 | SortOrder
55 | 3
56 | Summary
57 | This generates a new presenter using Uncle Bob's clean architecture. Your presentation logic goes here.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift/Presenter.xctemplate/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___PresentationLogic {
16 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response)
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresentationLogic {
20 | weak var viewController: ___VARIABLE_sceneName___DisplayLogic?
21 |
22 | // MARK: Parse and calc respnse from ___VARIABLE_sceneName___Interactor and send simple view model to ___VARIABLE_sceneName___ViewController to be displayed
23 |
24 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response) {
25 | let viewModel = ___VARIABLE_sceneName___.Something.ViewModel()
26 | viewController?.displaySomething(viewModel: viewModel)
27 | }
28 | //
29 | // func presentSomethingElse(response: ___VARIABLE_sceneName___.SomethingElse.Response) {
30 | // let viewModel = ___VARIABLE_sceneName___.SomethingElse.ViewModel()
31 | // viewController?.displaySomethingElse(viewModel: viewModel)
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/Clean Swift/Router.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Router.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Router.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Router.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Router.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new router using Uncle Bob's clean architecture. You navigate to other scenes by presenting and dismissing other view controllers here.
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___Router
38 | Description
39 | The router name
40 | Identifier
41 | routerName
42 | Name
43 | Router Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Platforms
51 |
52 | com.apple.platform.iphoneos
53 |
54 | SortOrder
55 | 6
56 | Summary
57 | This generates a new router using Uncle Bob's clean architecture. You navigate to other scenes by presenting and dismissing other view controllers here.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift/Router.xctemplate/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | @objc protocol ___VARIABLE_sceneName___RoutingLogic {
16 | //func routeToSomewhere(segue: UIStoryboardSegue?)
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataPassing {
20 | var dataStore: ___VARIABLE_sceneName___DataStore? { get }
21 | }
22 |
23 | class ___VARIABLE_sceneName___Router: NSObject, ___VARIABLE_sceneName___RoutingLogic, ___VARIABLE_sceneName___DataPassing {
24 | weak var viewController: ___VARIABLE_sceneName___ViewController?
25 | var dataStore: ___VARIABLE_sceneName___DataStore?
26 |
27 | // MARK: Routing (navigating to other screens)
28 |
29 | //func routeToSomewhere(segue: UIStoryboardSegue?) {
30 | // if let segue = segue {
31 | // let destinationVC = segue.destination as! SomewhereViewController
32 | // var destinationDS = destinationVC.router!.dataStore!
33 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
34 | // } else {
35 | // let storyboard = UIStoryboard(name: "Main", bundle: nil)
36 | // let destinationVC = storyboard.instantiateViewController(withIdentifier: "SomewhereViewController") as! SomewhereViewController
37 | // var destinationDS = destinationVC.router!.dataStore!
38 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
39 | // navigateToSomewhere(source: viewController!, destination: destinationVC)
40 | // }
41 | //}
42 |
43 | // MARK: Navigation to other screen
44 |
45 | //func navigateToSomewhere(source: ___VARIABLE_sceneName___ViewController, destination: SomewhereViewController) {
46 | // source.show(destination, sender: nil)
47 | //}
48 |
49 | // MARK: Passing data to other screen
50 |
51 | // func passDataToSomewhere(source: ___VARIABLE_sceneName___DataStore, destination: inout SomewhereDataStore) {
52 | // destination.name = source.name
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Scene.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Scene.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new scene using Uncle Bob's clean architecture. It consists of the view controller, interactor, presenter, and router. You can then create individual workers to supplement the interactor.
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___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___Presenter
66 | Description
67 | The presenter name
68 | Identifier
69 | presenterName
70 | Name
71 | Presenter Name:
72 | Required
73 |
74 | Type
75 | static
76 |
77 |
78 | Default
79 | ___VARIABLE_sceneName:identifier___Router
80 | Description
81 | The router name
82 | Identifier
83 | routerName
84 | Name
85 | Router Name:
86 | Required
87 |
88 | Type
89 | static
90 |
91 |
92 | Default
93 | ___VARIABLE_sceneName:identifier___Configurator
94 | Description
95 | The configurator name
96 | Identifier
97 | configuratorName
98 | Name
99 | Configurator Name:
100 | Required
101 |
102 | Type
103 | static
104 |
105 |
106 | Default
107 | ___VARIABLE_sceneName:identifier___Worker
108 | Description
109 | The worker name
110 | Identifier
111 | workerName
112 | Name
113 | Worker Name:
114 | Required
115 |
116 | Type
117 | static
118 |
119 |
120 | Default
121 | ___VARIABLE_sceneName:identifier___Models
122 | Description
123 | The model file name
124 | Identifier
125 | modelFileName
126 | Name
127 | Model File Name:
128 | Required
129 |
130 | Type
131 | static
132 |
133 |
134 | Default
135 | UIViewController
136 | Description
137 | What view controller class to subclass for the new scene
138 | FallbackHeader
139 | #import <UIKit/UIKit.h>
140 | Identifier
141 | viewControllerSubclass
142 | Name
143 | Subclass of:
144 | NotPersisted
145 |
146 | Required
147 | YES
148 | Type
149 | class
150 | Values
151 |
152 | UIViewController
153 | UITableViewController
154 | UICollectionViewController
155 |
156 |
157 |
158 | Platforms
159 |
160 | com.apple.platform.iphoneos
161 |
162 | SortOrder
163 | 0
164 | Summary
165 | This generates a new scene using Uncle Bob's clean architecture.
166 |
167 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___BusinessLogic {
16 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request)
17 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request)
18 | }
19 |
20 | protocol ___VARIABLE_sceneName___DataStore {
21 | //var name: String { get set }
22 | }
23 |
24 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___BusinessLogic, ___VARIABLE_sceneName___DataStore {
25 | var presenter: ___VARIABLE_sceneName___PresentationLogic?
26 | var worker: ___VARIABLE_sceneName___Worker?
27 | //var name: String = ""
28 |
29 | // MARK: Do something (and send response to ___VARIABLE_sceneName___Presenter)
30 |
31 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request) {
32 | worker = ___VARIABLE_sceneName___Worker()
33 | worker?.doSomeWork()
34 |
35 | let response = ___VARIABLE_sceneName___.Something.Response()
36 | presenter?.presentSomething(response: response)
37 | }
38 | //
39 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request) {
40 | // worker = ___VARIABLE_sceneName___Worker()
41 | // worker?.doSomeOtherWork()
42 | //
43 | // let response = ___VARIABLE_sceneName___.SomethingElse.Response()
44 | // presenter?.presentSomethingElse(response: response)
45 | // }
46 | }
47 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | enum ___VARIABLE_sceneName___
16 | {
17 | // MARK: Use cases
18 |
19 | enum Something
20 | {
21 | struct Request
22 | {
23 |
24 | }
25 |
26 | struct Response
27 | {
28 |
29 | }
30 |
31 | struct ViewModel
32 | {
33 |
34 | }
35 | }
36 |
37 | // enum SomethingElse
38 | // {
39 | // struct Request
40 | // {
41 | //
42 | // }
43 | //
44 | // struct Response
45 | // {
46 | //
47 | // }
48 | //
49 | // struct ViewModel
50 | // {
51 | //
52 | // }
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___PresentationLogic {
16 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response)
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresentationLogic {
20 | weak var viewController: ___VARIABLE_sceneName___DisplayLogic?
21 |
22 | // MARK: Parse and calc respnse from ___VARIABLE_sceneName___Interactor and send simple view model to ___VARIABLE_sceneName___ViewController to be displayed
23 |
24 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response) {
25 | let viewModel = ___VARIABLE_sceneName___.Something.ViewModel()
26 | viewController?.displaySomething(viewModel: viewModel)
27 | }
28 | //
29 | // func presentSomethingElse(response: ___VARIABLE_sceneName___.SomethingElse.Response) {
30 | // let viewModel = ___VARIABLE_sceneName___.SomethingElse.ViewModel()
31 | // viewController?.displaySomethingElse(viewModel: viewModel)
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | @objc protocol ___VARIABLE_sceneName___RoutingLogic {
16 | //func routeToSomewhere(segue: UIStoryboardSegue?)
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataPassing {
20 | var dataStore: ___VARIABLE_sceneName___DataStore? { get }
21 | }
22 |
23 | class ___VARIABLE_sceneName___Router: NSObject, ___VARIABLE_sceneName___RoutingLogic, ___VARIABLE_sceneName___DataPassing {
24 | weak var viewController: ___VARIABLE_sceneName___ViewController?
25 | var dataStore: ___VARIABLE_sceneName___DataStore?
26 |
27 | // MARK: Routing (navigating to other screens)
28 |
29 | //func routeToSomewhere(segue: UIStoryboardSegue?) {
30 | // if let segue = segue {
31 | // let destinationVC = segue.destination as! SomewhereViewController
32 | // var destinationDS = destinationVC.router!.dataStore!
33 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
34 | // } else {
35 | // let storyboard = UIStoryboard(name: "Main", bundle: nil)
36 | // let destinationVC = storyboard.instantiateViewController(withIdentifier: "SomewhereViewController") as! SomewhereViewController
37 | // var destinationDS = destinationVC.router!.dataStore!
38 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
39 | // navigateToSomewhere(source: viewController!, destination: destinationVC)
40 | // }
41 | //}
42 |
43 | // MARK: Navigation to other screen
44 |
45 | //func navigateToSomewhere(source: ___VARIABLE_sceneName___ViewController, destination: SomewhereViewController) {
46 | // source.show(destination, sender: nil)
47 | //}
48 |
49 | // MARK: Passing data to other screen
50 |
51 | // func passDataToSomewhere(source: ___VARIABLE_sceneName___DataStore, destination: inout SomewhereDataStore) {
52 | // destination.name = source.name
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class {
16 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
17 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
18 | }
19 |
20 | class ___VARIABLE_sceneName___ViewController: UICollectionViewController, ___VARIABLE_sceneName___DisplayLogic {
21 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
22 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
23 |
24 | // MARK: Object lifecycle
25 |
26 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
27 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
28 | setup()
29 | }
30 |
31 | required init?(coder aDecoder: NSCoder) {
32 | super.init(coder: aDecoder)
33 | setup()
34 | }
35 |
36 | // MARK: - Setup Clean Code Design Pattern
37 |
38 | private func setup() {
39 | let viewController = self
40 | let interactor = ___VARIABLE_sceneName___Interactor()
41 | let presenter = ___VARIABLE_sceneName___Presenter()
42 | let router = ___VARIABLE_sceneName___Router()
43 | viewController.interactor = interactor
44 | viewController.router = router
45 | interactor.presenter = presenter
46 | presenter.viewController = viewController
47 | router.viewController = viewController
48 | router.dataStore = interactor
49 | }
50 |
51 | // MARK: - Routing
52 |
53 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
54 | if let scene = segue.identifier {
55 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
56 | if let router = router, router.responds(to: selector) {
57 | router.perform(selector, with: segue)
58 | }
59 | }
60 | }
61 |
62 | // MARK: - View lifecycle
63 |
64 | override func viewDidLoad() {
65 | super.viewDidLoad()
66 | doSomething()
67 | // doSomethingElse()
68 | }
69 |
70 | //MARK: - receive events from UI
71 | //@IBOutlet weak var nameTextField: UITextField!
72 |
73 | // @IBAction func cancelButtonTapped(_ sender: Any) {
74 | //
75 | // }
76 | //
77 | // @IBAction func confirmButtonTapped(_ sender: Any) {
78 | //
79 | // }
80 | //
81 |
82 | // MARK: - request data from ___VARIABLE_sceneName___Interactor
83 |
84 | //@IBOutlet weak var nameTextField: UITextField!
85 |
86 | func doSomething() {
87 | let request = ___VARIABLE_sceneName___.Something.Request()
88 | interactor?.doSomething(request: request)
89 | }
90 | //
91 | // func doSomethingElse() {
92 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
93 | // interactor?.doSomethingElse(request: request)
94 | // }
95 |
96 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
97 |
98 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
99 | //nameTextField.text = viewModel.name
100 | }
101 | //
102 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
103 | // // do sometingElse with viewModel
104 | // }
105 | }
106 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UICollectionViewController/___FILEBASENAME___Worker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | class ___VARIABLE_sceneName___Worker {
16 | func doSomeWork() {
17 |
18 | }
19 | //
20 | // func doSomeOtherWork() {
21 | //
22 | // }
23 | }
24 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___BusinessLogic {
16 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request)
17 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request)
18 | }
19 |
20 | protocol ___VARIABLE_sceneName___DataStore {
21 | //var name: String { get set }
22 | }
23 |
24 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___BusinessLogic, ___VARIABLE_sceneName___DataStore {
25 | var presenter: ___VARIABLE_sceneName___PresentationLogic?
26 | var worker: ___VARIABLE_sceneName___Worker?
27 | //var name: String = ""
28 |
29 | // MARK: Do something (and send response to ___VARIABLE_sceneName___Presenter)
30 |
31 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request) {
32 | worker = ___VARIABLE_sceneName___Worker()
33 | worker?.doSomeWork()
34 |
35 | let response = ___VARIABLE_sceneName___.Something.Response()
36 | presenter?.presentSomething(response: response)
37 | }
38 | //
39 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request) {
40 | // worker = ___VARIABLE_sceneName___Worker()
41 | // worker?.doSomeOtherWork()
42 | //
43 | // let response = ___VARIABLE_sceneName___.SomethingElse.Response()
44 | // presenter?.presentSomethingElse(response: response)
45 | // }
46 | }
47 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | enum ___VARIABLE_sceneName___
16 | {
17 | // MARK: Use cases
18 |
19 | enum Something
20 | {
21 | struct Request
22 | {
23 |
24 | }
25 |
26 | struct Response
27 | {
28 |
29 | }
30 |
31 | struct ViewModel
32 | {
33 |
34 | }
35 | }
36 |
37 | // enum SomethingElse
38 | // {
39 | // struct Request
40 | // {
41 | //
42 | // }
43 | //
44 | // struct Response
45 | // {
46 | //
47 | // }
48 | //
49 | // struct ViewModel
50 | // {
51 | //
52 | // }
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___PresentationLogic {
16 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response)
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresentationLogic {
20 | weak var viewController: ___VARIABLE_sceneName___DisplayLogic?
21 |
22 | // MARK: Parse and calc respnse from ___VARIABLE_sceneName___Interactor and send simple view model to ___VARIABLE_sceneName___ViewController to be displayed
23 |
24 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response) {
25 | let viewModel = ___VARIABLE_sceneName___.Something.ViewModel()
26 | viewController?.displaySomething(viewModel: viewModel)
27 | }
28 | //
29 | // func presentSomethingElse(response: ___VARIABLE_sceneName___.SomethingElse.Response) {
30 | // let viewModel = ___VARIABLE_sceneName___.SomethingElse.ViewModel()
31 | // viewController?.displaySomethingElse(viewModel: viewModel)
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | @objc protocol ___VARIABLE_sceneName___RoutingLogic {
16 | //func routeToSomewhere(segue: UIStoryboardSegue?)
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataPassing {
20 | var dataStore: ___VARIABLE_sceneName___DataStore? { get }
21 | }
22 |
23 | class ___VARIABLE_sceneName___Router: NSObject, ___VARIABLE_sceneName___RoutingLogic, ___VARIABLE_sceneName___DataPassing {
24 | weak var viewController: ___VARIABLE_sceneName___ViewController?
25 | var dataStore: ___VARIABLE_sceneName___DataStore?
26 |
27 | // MARK: Routing (navigating to other screens)
28 |
29 | //func routeToSomewhere(segue: UIStoryboardSegue?) {
30 | // if let segue = segue {
31 | // let destinationVC = segue.destination as! SomewhereViewController
32 | // var destinationDS = destinationVC.router!.dataStore!
33 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
34 | // } else {
35 | // let storyboard = UIStoryboard(name: "Main", bundle: nil)
36 | // let destinationVC = storyboard.instantiateViewController(withIdentifier: "SomewhereViewController") as! SomewhereViewController
37 | // var destinationDS = destinationVC.router!.dataStore!
38 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
39 | // navigateToSomewhere(source: viewController!, destination: destinationVC)
40 | // }
41 | //}
42 |
43 | // MARK: Navigation to other screen
44 |
45 | //func navigateToSomewhere(source: ___VARIABLE_sceneName___ViewController, destination: SomewhereViewController) {
46 | // source.show(destination, sender: nil)
47 | //}
48 |
49 | // MARK: Passing data to other screen
50 |
51 | // func passDataToSomewhere(source: ___VARIABLE_sceneName___DataStore, destination: inout SomewhereDataStore) {
52 | // destination.name = source.name
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class {
16 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
17 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
18 | }
19 |
20 | class ___VARIABLE_sceneName___ViewController: UITableViewController, ___VARIABLE_sceneName___DisplayLogic {
21 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
22 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
23 |
24 | // MARK: Object lifecycle
25 |
26 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
27 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
28 | setup()
29 | }
30 |
31 | required init?(coder aDecoder: NSCoder) {
32 | super.init(coder: aDecoder)
33 | setup()
34 | }
35 |
36 | // MARK: - Setup Clean Code Design Pattern
37 |
38 | private func setup() {
39 | let viewController = self
40 | let interactor = ___VARIABLE_sceneName___Interactor()
41 | let presenter = ___VARIABLE_sceneName___Presenter()
42 | let router = ___VARIABLE_sceneName___Router()
43 | viewController.interactor = interactor
44 | viewController.router = router
45 | interactor.presenter = presenter
46 | presenter.viewController = viewController
47 | router.viewController = viewController
48 | router.dataStore = interactor
49 | }
50 |
51 | // MARK: - Routing
52 |
53 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
54 | if let scene = segue.identifier {
55 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
56 | if let router = router, router.responds(to: selector) {
57 | router.perform(selector, with: segue)
58 | }
59 | }
60 | }
61 |
62 | // MARK: - View lifecycle
63 |
64 | override func viewDidLoad() {
65 | super.viewDidLoad()
66 | doSomething()
67 | // doSomethingElse()
68 | }
69 |
70 | //MARK: - receive events from UI
71 | //@IBOutlet weak var nameTextField: UITextField!
72 |
73 | // @IBAction func cancelButtonTapped(_ sender: Any) {
74 | //
75 | // }
76 | //
77 | // @IBAction func confirmButtonTapped(_ sender: Any) {
78 | //
79 | // }
80 | //
81 |
82 | // MARK: - request data from ___VARIABLE_sceneName___Interactor
83 |
84 | //@IBOutlet weak var nameTextField: UITextField!
85 |
86 | func doSomething() {
87 | let request = ___VARIABLE_sceneName___.Something.Request()
88 | interactor?.doSomething(request: request)
89 | }
90 | //
91 | // func doSomethingElse() {
92 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
93 | // interactor?.doSomethingElse(request: request)
94 | // }
95 |
96 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
97 |
98 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
99 | //nameTextField.text = viewModel.name
100 | }
101 | //
102 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
103 | // // do sometingElse with viewModel
104 | // }
105 | }
106 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UITableViewController/___FILEBASENAME___Worker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | class ___VARIABLE_sceneName___Worker {
16 | func doSomeWork() {
17 |
18 | }
19 | //
20 | // func doSomeOtherWork() {
21 | //
22 | // }
23 | }
24 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UIViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___BusinessLogic {
16 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request)
17 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request)
18 | }
19 |
20 | protocol ___VARIABLE_sceneName___DataStore {
21 | //var name: String { get set }
22 | }
23 |
24 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___BusinessLogic, ___VARIABLE_sceneName___DataStore {
25 | var presenter: ___VARIABLE_sceneName___PresentationLogic?
26 | var worker: ___VARIABLE_sceneName___Worker?
27 | //var name: String = ""
28 |
29 | // MARK: Do something (and send response to ___VARIABLE_sceneName___Presenter)
30 |
31 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request) {
32 | worker = ___VARIABLE_sceneName___Worker()
33 | worker?.doSomeWork()
34 |
35 | let response = ___VARIABLE_sceneName___.Something.Response()
36 | presenter?.presentSomething(response: response)
37 | }
38 | //
39 | // func doSomethingElse(request: ___VARIABLE_sceneName___.SomethingElse.Request) {
40 | // worker = ___VARIABLE_sceneName___Worker()
41 | // worker?.doSomeOtherWork()
42 | //
43 | // let response = ___VARIABLE_sceneName___.SomethingElse.Response()
44 | // presenter?.presentSomethingElse(response: response)
45 | // }
46 | }
47 |
--------------------------------------------------------------------------------
/Clean Swift/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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | enum ___VARIABLE_sceneName___
16 | {
17 | // MARK: Use cases
18 |
19 | enum Something
20 | {
21 | struct Request
22 | {
23 |
24 | }
25 |
26 | struct Response
27 | {
28 |
29 | }
30 |
31 | struct ViewModel
32 | {
33 |
34 | }
35 | }
36 |
37 | // enum SomethingElse
38 | // {
39 | // struct Request
40 | // {
41 | //
42 | // }
43 | //
44 | // struct Response
45 | // {
46 | //
47 | // }
48 | //
49 | // struct ViewModel
50 | // {
51 | //
52 | // }
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___PresentationLogic {
16 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response)
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresentationLogic {
20 | weak var viewController: ___VARIABLE_sceneName___DisplayLogic?
21 |
22 | // MARK: Parse and calc respnse from ___VARIABLE_sceneName___Interactor and send simple view model to ___VARIABLE_sceneName___ViewController to be displayed
23 |
24 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response) {
25 | let viewModel = ___VARIABLE_sceneName___.Something.ViewModel()
26 | viewController?.displaySomething(viewModel: viewModel)
27 | }
28 | //
29 | // func presentSomethingElse(response: ___VARIABLE_sceneName___.SomethingElse.Response) {
30 | // let viewModel = ___VARIABLE_sceneName___.SomethingElse.ViewModel()
31 | // viewController?.displaySomethingElse(viewModel: viewModel)
32 | // }
33 | }
34 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UIViewController/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | @objc protocol ___VARIABLE_sceneName___RoutingLogic {
16 | //func routeToSomewhere(segue: UIStoryboardSegue?)
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataPassing {
20 | var dataStore: ___VARIABLE_sceneName___DataStore? { get }
21 | }
22 |
23 | class ___VARIABLE_sceneName___Router: NSObject, ___VARIABLE_sceneName___RoutingLogic, ___VARIABLE_sceneName___DataPassing {
24 | weak var viewController: ___VARIABLE_sceneName___ViewController?
25 | var dataStore: ___VARIABLE_sceneName___DataStore?
26 |
27 | // MARK: Routing (navigating to other screens)
28 |
29 | //func routeToSomewhere(segue: UIStoryboardSegue?) {
30 | // if let segue = segue {
31 | // let destinationVC = segue.destination as! SomewhereViewController
32 | // var destinationDS = destinationVC.router!.dataStore!
33 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
34 | // } else {
35 | // let storyboard = UIStoryboard(name: "Main", bundle: nil)
36 | // let destinationVC = storyboard.instantiateViewController(withIdentifier: "SomewhereViewController") as! SomewhereViewController
37 | // var destinationDS = destinationVC.router!.dataStore!
38 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
39 | // navigateToSomewhere(source: viewController!, destination: destinationVC)
40 | // }
41 | //}
42 |
43 | // MARK: Navigation to other screen
44 |
45 | //func navigateToSomewhere(source: ___VARIABLE_sceneName___ViewController, destination: SomewhereViewController) {
46 | // source.show(destination, sender: nil)
47 | //}
48 |
49 | // MARK: Passing data to other screen
50 |
51 | // func passDataToSomewhere(source: ___VARIABLE_sceneName___DataStore, destination: inout SomewhereDataStore) {
52 | // destination.name = source.name
53 | // }
54 | }
55 |
--------------------------------------------------------------------------------
/Clean Swift/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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class
16 | {
17 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
18 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UIViewController, ___VARIABLE_sceneName___DisplayLogic {
22 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
23 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
24 |
25 | // MARK: Object lifecycle
26 |
27 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
28 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
29 | setup()
30 | }
31 |
32 | required init?(coder aDecoder: NSCoder) {
33 | super.init(coder: aDecoder)
34 | setup()
35 | }
36 |
37 | // MARK: - Setup Clean Code Design Pattern
38 |
39 | private func setup() {
40 | let viewController = self
41 | let interactor = ___VARIABLE_sceneName___Interactor()
42 | let presenter = ___VARIABLE_sceneName___Presenter()
43 | let router = ___VARIABLE_sceneName___Router()
44 | viewController.interactor = interactor
45 | viewController.router = router
46 | interactor.presenter = presenter
47 | presenter.viewController = viewController
48 | router.viewController = viewController
49 | router.dataStore = interactor
50 | }
51 |
52 | // MARK: - Routing
53 |
54 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
55 | if let scene = segue.identifier {
56 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
57 | if let router = router, router.responds(to: selector) {
58 | router.perform(selector, with: segue)
59 | }
60 | }
61 | }
62 |
63 | // MARK: - View lifecycle
64 |
65 | override func viewDidLoad() {
66 | super.viewDidLoad()
67 | doSomething()
68 | // doSomethingElse()
69 | }
70 |
71 | //MARK: - receive events from UI
72 |
73 | //@IBOutlet weak var nameTextField: UITextField!
74 | //
75 | // @IBAction func someButtonTapped(_ sender: Any) {
76 | //
77 | // }
78 | //
79 | // @IBAction func otherButtonTapped(_ sender: Any) {
80 | //
81 | // }
82 |
83 | // MARK: - request data from ___VARIABLE_sceneName___Interactor
84 |
85 | func doSomething() {
86 | let request = ___VARIABLE_sceneName___.Something.Request()
87 | interactor?.doSomething(request: request)
88 | }
89 | //
90 | // func doSomethingElse() {
91 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
92 | // interactor?.doSomethingElse(request: request)
93 | // }
94 |
95 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
96 |
97 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
98 | //nameTextField.text = viewModel.name
99 | }
100 | //
101 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
102 | // // do sometingElse with viewModel
103 | // }
104 | }
105 |
--------------------------------------------------------------------------------
/Clean Swift/Scene.xctemplate/UIViewController/___FILEBASENAME___Worker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | class ___VARIABLE_sceneName___Worker {
16 | func doSomeWork() {
17 |
18 | }
19 | //
20 | // func doSomeOtherWork() {
21 | //
22 | // }
23 | }
24 |
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Unit Tests.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Unit Tests.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates unit tests for your scene using Uncle Bob's clean architecture. It consists of three test files for view controller, interactor, and presenter.
9 | Kind
10 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
11 | Options
12 |
13 |
14 | Description
15 | The name of the scene to create tests for
16 | Identifier
17 | sceneName
18 | Name
19 | 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___ViewControllerTests
38 | Description
39 | The view controller tests name
40 | Identifier
41 | viewControllerTestsName
42 | Name
43 | View Controller Tests Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Default
51 | ___VARIABLE_sceneName:identifier___InteractorTests
52 | Description
53 | The interactor tests name
54 | Identifier
55 | interactorTestsName
56 | Name
57 | Interactor Tests Name:
58 | Required
59 |
60 | Type
61 | static
62 |
63 |
64 | Default
65 | ___VARIABLE_sceneName:identifier___PresenterTests
66 | Description
67 | The presenter tests name
68 | Identifier
69 | presenterTestsName
70 | Name
71 | Presenter Tests Name:
72 | Required
73 |
74 | Type
75 | static
76 |
77 |
78 | Default
79 | ___VARIABLE_sceneName:identifier___WorkerTests
80 | Description
81 | The worker tests name
82 | Identifier
83 | workerTestsName
84 | Name
85 | Worker Tests Name:
86 | Required
87 |
88 | Type
89 | static
90 |
91 |
92 | Platforms
93 |
94 | com.apple.platform.iphoneos
95 |
96 | SortOrder
97 | 7
98 | Summary
99 | This generates unit tests for your scene using Uncle Bob's clean architecture.
100 |
101 |
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/___FILEBASENAME___InteractorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | @testable import ___PROJECTNAMEASIDENTIFIER___
14 | import XCTest
15 |
16 | class ___VARIABLE_sceneName___InteractorTests: XCTestCase
17 | {
18 | // MARK: Subject under test
19 |
20 | var sut: ___VARIABLE_sceneName___Interactor!
21 |
22 | // MARK: - Test lifecycle
23 |
24 | override func setUp() {
25 | super.setUp()
26 | setup___VARIABLE_sceneName___Interactor()
27 | }
28 |
29 | override func tearDown() {
30 | super.tearDown()
31 | }
32 |
33 | // MARK: - Test setup
34 |
35 | func setup___VARIABLE_sceneName___Interactor() {
36 | sut = ___VARIABLE_sceneName___Interactor()
37 | }
38 |
39 | // MARK: - Test doubles
40 |
41 | class ___VARIABLE_sceneName___PresentationLogicSpy: ___VARIABLE_sceneName___PresentationLogic
42 | {
43 | var presentSomethingCalled = false
44 |
45 | func presentSomething(response: ___VARIABLE_sceneName___.Something.Response) {
46 | presentSomethingCalled = true
47 | }
48 | }
49 |
50 | // MARK: - Tests
51 |
52 | func testDoSomething() {
53 | // Given
54 | let spy = ___VARIABLE_sceneName___PresentationLogicSpy()
55 | sut.presenter = spy
56 | let request = ___VARIABLE_sceneName___.Something.Request()
57 |
58 | // When
59 | sut.doSomething(request: request)
60 |
61 | // Then
62 | XCTAssertTrue(spy.presentSomethingCalled, "doSomething(request:) should ask the presenter to format the result")
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/___FILEBASENAME___PresenterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | @testable import ___PROJECTNAMEASIDENTIFIER___
14 | import XCTest
15 |
16 | class ___VARIABLE_sceneName___PresenterTests: XCTestCase {
17 | // MARK: Subject under test
18 |
19 | var sut: ___VARIABLE_sceneName___Presenter!
20 |
21 | // MARK: - Test lifecycle
22 |
23 | override func setUp() {
24 | super.setUp()
25 | setup___VARIABLE_sceneName___Presenter()
26 | }
27 |
28 | override func tearDown() {
29 | super.tearDown()
30 | }
31 |
32 | // MARK: - Test setup
33 |
34 | func setup___VARIABLE_sceneName___Presenter() {
35 | sut = ___VARIABLE_sceneName___Presenter()
36 | }
37 |
38 | // MARK: - Test doubles
39 |
40 | class ___VARIABLE_sceneName___DisplayLogicSpy: ___VARIABLE_sceneName___DisplayLogic {
41 | var displaySomethingCalled = false
42 |
43 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
44 | displaySomethingCalled = true
45 | }
46 | }
47 |
48 | // MARK: - Tests
49 |
50 | func testPresentSomething() {
51 | // Given
52 | let spy = ___VARIABLE_sceneName___DisplayLogicSpy()
53 | sut.viewController = spy
54 | let response = ___VARIABLE_sceneName___.Something.Response()
55 |
56 | // When
57 | sut.presentSomething(response: response)
58 |
59 | // Then
60 | XCTAssertTrue(spy.displaySomethingCalled, "presentSomething(response:) should ask the view controller to display the result")
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/___FILEBASENAME___ViewControllerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | @testable import ___PROJECTNAMEASIDENTIFIER___
14 | import XCTest
15 |
16 | class ___VARIABLE_sceneName___ViewControllerTests: XCTestCase {
17 | // MARK: Subject under test
18 |
19 | var sut: ___VARIABLE_sceneName___ViewController!
20 | var window: UIWindow!
21 |
22 | // MARK: - Test lifecycle
23 |
24 | override func setUp() {
25 | super.setUp()
26 | window = UIWindow()
27 | setup___VARIABLE_sceneName___ViewController()
28 | }
29 |
30 | override func tearDown() {
31 | window = nil
32 | super.tearDown()
33 | }
34 |
35 | // MARK: - Test setup
36 |
37 | func setup___VARIABLE_sceneName___ViewController() {
38 | let bundle = Bundle.main
39 | let storyboard = UIStoryboard(name: "Main", bundle: bundle)
40 | sut = storyboard.instantiateViewController(withIdentifier: "___VARIABLE_sceneName___ViewController") as! ___VARIABLE_sceneName___ViewController
41 | }
42 |
43 | func loadView() {
44 | window.addSubview(sut.view)
45 | RunLoop.current.run(until: Date())
46 | }
47 |
48 | // MARK: - Test doubles
49 |
50 | class ___VARIABLE_sceneName___BusinessLogicSpy: ___VARIABLE_sceneName___BusinessLogic {
51 | var doSomethingCalled = false
52 |
53 | func doSomething(request: ___VARIABLE_sceneName___.Something.Request)
54 | {
55 | doSomethingCalled = true
56 | }
57 | }
58 |
59 | // MARK: - Tests
60 |
61 | func testShouldDoSomethingWhenViewIsLoaded() {
62 | // Given
63 | let spy = ___VARIABLE_sceneName___BusinessLogicSpy()
64 | sut.interactor = spy
65 |
66 | // When
67 | loadView()
68 |
69 | // Then
70 | XCTAssertTrue(spy.doSomethingCalled, "viewDidLoad() should ask the interactor to do something")
71 | }
72 |
73 | func testDisplaySomething() {
74 | // Given
75 | let viewModel = ___VARIABLE_sceneName___.Something.ViewModel()
76 |
77 | // When
78 | loadView()
79 | sut.displaySomething(viewModel: viewModel)
80 |
81 | // Then
82 | //XCTAssertEqual(sut.nameTextField.text, "", "displaySomething(viewModel:) should update the name text field")
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Clean Swift/Unit Tests.xctemplate/___FILEBASENAME___WorkerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | @testable import ___PROJECTNAMEASIDENTIFIER___
14 | import XCTest
15 |
16 | class ___VARIABLE_sceneName___WorkerTests: XCTestCase
17 | {
18 | // MARK: Subject under test
19 |
20 | var sut: ___VARIABLE_sceneName___Worker!
21 |
22 | // MARK: - Test lifecycle
23 |
24 | override func setUp() {
25 | super.setUp()
26 | setup___VARIABLE_sceneName___Worker()
27 | }
28 |
29 | override func tearDown() {
30 | super.tearDown()
31 | }
32 |
33 | // MARK: - Test setup
34 |
35 | func setup___VARIABLE_sceneName___Worker() {
36 | sut = ___VARIABLE_sceneName___Worker()
37 | }
38 |
39 | // MARK: - Test doubles
40 |
41 | // MARK: - Tests
42 |
43 | func testSomething() {
44 | // Given
45 |
46 | // When
47 |
48 | // Then
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Clean Swift/View Controller.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/View Controller.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/View Controller.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/View Controller.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/View Controller.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new view controller using Uncle Bob's clean architecture. Your view/view controller logic goes here.
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 | UIViewController
52 | Description
53 | What view controller class to subclass for the new scene
54 | FallbackHeader
55 | #import <UIKit/UIKit.h>
56 | Identifier
57 | viewControllerSubclass
58 | Name
59 | Subclass of:
60 | NotPersisted
61 |
62 | Required
63 | YES
64 | Type
65 | class
66 | Values
67 |
68 | UIViewController
69 | UITableViewController
70 | UICollectionViewController
71 |
72 |
73 |
74 | Platforms
75 |
76 | com.apple.platform.iphoneos
77 |
78 | SortOrder
79 | 1
80 | Summary
81 | This generates a new view controller using Uncle Bob's clean architecture. Your view/view controller logic goes here.
82 |
83 |
--------------------------------------------------------------------------------
/Clean Swift/View Controller.xctemplate/UICollectionViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class {
16 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
17 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
18 | }
19 |
20 | class ___VARIABLE_sceneName___ViewController: UICollectionViewController, ___VARIABLE_sceneName___DisplayLogic {
21 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
22 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
23 |
24 | // MARK: Object lifecycle
25 |
26 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
27 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
28 | setup()
29 | }
30 |
31 | required init?(coder aDecoder: NSCoder) {
32 | super.init(coder: aDecoder)
33 | setup()
34 | }
35 |
36 | // MARK: - Setup Clean Code Design Pattern
37 |
38 | private func setup() {
39 | let viewController = self
40 | let interactor = ___VARIABLE_sceneName___Interactor()
41 | let presenter = ___VARIABLE_sceneName___Presenter()
42 | let router = ___VARIABLE_sceneName___Router()
43 | viewController.interactor = interactor
44 | viewController.router = router
45 | interactor.presenter = presenter
46 | presenter.viewController = viewController
47 | router.viewController = viewController
48 | router.dataStore = interactor
49 | }
50 |
51 | // MARK: - Routing
52 |
53 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
54 | if let scene = segue.identifier {
55 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
56 | if let router = router, router.responds(to: selector) {
57 | router.perform(selector, with: segue)
58 | }
59 | }
60 | }
61 |
62 | // MARK: - View lifecycle
63 |
64 | override func viewDidLoad() {
65 | super.viewDidLoad()
66 | doSomething()
67 | // doSomethingElse()
68 | }
69 |
70 | //MARK: - receive events from UI
71 | //@IBOutlet weak var nameTextField: UITextField!
72 |
73 | // @IBAction func cancelButtonTapped(_ sender: Any) {
74 | //
75 | // }
76 | //
77 | // @IBAction func confirmButtonTapped(_ sender: Any) {
78 | //
79 | // }
80 | //
81 |
82 | // MARK: - request data from ___VARIABLE_sceneName___Interactor
83 |
84 | //@IBOutlet weak var nameTextField: UITextField!
85 |
86 | func doSomething() {
87 | let request = ___VARIABLE_sceneName___.Something.Request()
88 | interactor?.doSomething(request: request)
89 | }
90 | //
91 | // func doSomethingElse() {
92 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
93 | // interactor?.doSomethingElse(request: request)
94 | // }
95 |
96 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
97 |
98 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
99 | //nameTextField.text = viewModel.name
100 | }
101 | //
102 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
103 | // // do sometingElse with viewModel
104 | // }
105 | }
106 |
--------------------------------------------------------------------------------
/Clean Swift/View Controller.xctemplate/UITableViewController/___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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class {
16 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
17 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
18 | }
19 |
20 | class ___VARIABLE_sceneName___ViewController: UITableViewController, ___VARIABLE_sceneName___DisplayLogic {
21 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
22 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
23 |
24 | // MARK: Object lifecycle
25 |
26 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
27 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
28 | setup()
29 | }
30 |
31 | required init?(coder aDecoder: NSCoder) {
32 | super.init(coder: aDecoder)
33 | setup()
34 | }
35 |
36 | // MARK: - Setup Clean Code Design Pattern
37 |
38 | private func setup() {
39 | let viewController = self
40 | let interactor = ___VARIABLE_sceneName___Interactor()
41 | let presenter = ___VARIABLE_sceneName___Presenter()
42 | let router = ___VARIABLE_sceneName___Router()
43 | viewController.interactor = interactor
44 | viewController.router = router
45 | interactor.presenter = presenter
46 | presenter.viewController = viewController
47 | router.viewController = viewController
48 | router.dataStore = interactor
49 | }
50 |
51 | // MARK: - Routing
52 |
53 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
54 | if let scene = segue.identifier {
55 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
56 | if let router = router, router.responds(to: selector) {
57 | router.perform(selector, with: segue)
58 | }
59 | }
60 | }
61 |
62 | // MARK: - View lifecycle
63 |
64 | override func viewDidLoad() {
65 | super.viewDidLoad()
66 | doSomething()
67 | // doSomethingElse()
68 | }
69 |
70 | //MARK: - receive events from UI
71 | //@IBOutlet weak var nameTextField: UITextField!
72 |
73 | // @IBAction func cancelButtonTapped(_ sender: Any) {
74 | //
75 | // }
76 | //
77 | // @IBAction func confirmButtonTapped(_ sender: Any) {
78 | //
79 | // }
80 | //
81 |
82 | //@IBOutlet weak var nameTextField: UITextField!
83 |
84 | func doSomething() {
85 | let request = ___VARIABLE_sceneName___.Something.Request()
86 | interactor?.doSomething(request: request)
87 | }
88 | //
89 | // func doSomethingElse() {
90 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
91 | // interactor?.doSomethingElse(request: request)
92 | // }
93 |
94 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
95 |
96 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
97 | //nameTextField.text = viewModel.name
98 | }
99 | //
100 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
101 | // // do sometingElse with viewModel
102 | // }
103 | }
104 |
--------------------------------------------------------------------------------
/Clean Swift/View Controller.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 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol ___VARIABLE_sceneName___DisplayLogic: class
16 | {
17 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel)
18 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel)
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UIViewController, ___VARIABLE_sceneName___DisplayLogic {
22 | var interactor: ___VARIABLE_sceneName___BusinessLogic?
23 | var router: (NSObjectProtocol & ___VARIABLE_sceneName___RoutingLogic & ___VARIABLE_sceneName___DataPassing)?
24 |
25 | // MARK: Object lifecycle
26 |
27 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
28 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
29 | setup()
30 | }
31 |
32 | required init?(coder aDecoder: NSCoder) {
33 | super.init(coder: aDecoder)
34 | setup()
35 | }
36 |
37 | // MARK: - Setup Clean Code Design Pattern
38 |
39 | private func setup() {
40 | let viewController = self
41 | let interactor = ___VARIABLE_sceneName___Interactor()
42 | let presenter = ___VARIABLE_sceneName___Presenter()
43 | let router = ___VARIABLE_sceneName___Router()
44 | viewController.interactor = interactor
45 | viewController.router = router
46 | interactor.presenter = presenter
47 | presenter.viewController = viewController
48 | router.viewController = viewController
49 | router.dataStore = interactor
50 | }
51 |
52 | // MARK: - Routing
53 |
54 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
55 | if let scene = segue.identifier {
56 | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:")
57 | if let router = router, router.responds(to: selector) {
58 | router.perform(selector, with: segue)
59 | }
60 | }
61 | }
62 |
63 | // MARK: - View lifecycle
64 |
65 | override func viewDidLoad() {
66 | super.viewDidLoad()
67 | doSomething()
68 | // doSomethingElse()
69 | }
70 |
71 | //MARK: - receive events from UI
72 | //@IBOutlet weak var nameTextField: UITextField!
73 |
74 | // @IBAction func cancelButtonTapped(_ sender: Any) {
75 | //
76 | // }
77 | //
78 | // @IBAction func confirmButtonTapped(_ sender: Any) {
79 | //
80 | // }
81 | //
82 |
83 | // MARK: - request data from ___VARIABLE_sceneName___Interactor
84 |
85 | //@IBOutlet weak var nameTextField: UITextField!
86 |
87 | func doSomething() {
88 | let request = ___VARIABLE_sceneName___.Something.Request()
89 | interactor?.doSomething(request: request)
90 | }
91 | //
92 | // func doSomethingElse() {
93 | // let request = ___VARIABLE_sceneName___.SomethingElse.Request()
94 | // interactor?.doSomethingElse(request: request)
95 | // }
96 |
97 | // MARK: - display view model from ___VARIABLE_sceneName___Presenter
98 |
99 | func displaySomething(viewModel: ___VARIABLE_sceneName___.Something.ViewModel) {
100 | //nameTextField.text = viewModel.name
101 | }
102 | //
103 | // func displaySomethingElse(viewModel: ___VARIABLE_sceneName___.SomethingElse.ViewModel) {
104 | // // do sometingElse with viewModel
105 | // }
106 | }
107 |
--------------------------------------------------------------------------------
/Clean Swift/Worker.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Worker.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift/Worker.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/Clean Swift/Worker.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift/Worker.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new worker to perform your specific business logic.
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___Worker
38 | Description
39 | The worker name
40 | Identifier
41 | workerName
42 | Name
43 | Worker Name:
44 | Required
45 |
46 | Type
47 | static
48 |
49 |
50 | Platforms
51 |
52 | com.apple.platform.iphoneos
53 |
54 | SortOrder
55 | 5
56 | Summary
57 | This generates a new worker to perform your specific business logic.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift/Worker.xctemplate/___FILEBASENAME___Worker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // ___PROJECTNAME___
4 | //
5 | // Created by ___FULLUSERNAME___ on ___DATE___.
6 | // Copyright (c) ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | class ___VARIABLE_sceneName___Worker {
16 | func doSomeWork() {
17 |
18 | }
19 | //
20 | // func doSomeOtherWork() {
21 | //
22 | // }
23 | }
24 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | E90CB4B4254B8C3C0083ECD3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4B3254B8C3C0083ECD3 /* AppDelegate.swift */; };
11 | E90CB4B6254B8C3C0083ECD3 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4B5254B8C3C0083ECD3 /* SceneDelegate.swift */; };
12 | E90CB4B8254B8C3C0083ECD3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4B7254B8C3C0083ECD3 /* ViewController.swift */; };
13 | E90CB4BB254B8C3C0083ECD3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E90CB4B9254B8C3C0083ECD3 /* Main.storyboard */; };
14 | E90CB4BD254B8C3F0083ECD3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E90CB4BC254B8C3F0083ECD3 /* Assets.xcassets */; };
15 | E90CB4C0254B8C3F0083ECD3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E90CB4BE254B8C3F0083ECD3 /* LaunchScreen.storyboard */; };
16 | E90CB4CB254B8C3F0083ECD3 /* CleanSwiftExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4CA254B8C3F0083ECD3 /* CleanSwiftExampleTests.swift */; };
17 | E90CB4D6254B8C3F0083ECD3 /* CleanSwiftExampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4D5254B8C3F0083ECD3 /* CleanSwiftExampleUITests.swift */; };
18 | E90CB4ED254B8C6C0083ECD3 /* LoginPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4E7254B8C6C0083ECD3 /* LoginPresenter.swift */; };
19 | E90CB4EF254B8C6C0083ECD3 /* LoginRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4E9254B8C6C0083ECD3 /* LoginRouter.swift */; };
20 | E90CB4F0254B8C6C0083ECD3 /* LoginModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4EA254B8C6C0083ECD3 /* LoginModels.swift */; };
21 | E90CB4F1254B8C6C0083ECD3 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4EB254B8C6C0083ECD3 /* LoginViewController.swift */; };
22 | E90CB4F2254B8C6C0083ECD3 /* LoginInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90CB4EC254B8C6C0083ECD3 /* LoginInteractor.swift */; };
23 | E94DB10B254DFAC2009215FA /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94DB10A254DFAC2009215FA /* User.swift */; };
24 | E94DB122254E19A5009215FA /* LoginViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E94DB121254E19A5009215FA /* LoginViewController.storyboard */; };
25 | E94DB12B254E1AF1009215FA /* HomeViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E94DB12A254E1AF1009215FA /* HomeViewController.storyboard */; };
26 | E94DB130254E1B02009215FA /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94DB12F254E1B02009215FA /* HomeViewController.swift */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXContainerItemProxy section */
30 | E90CB4C7254B8C3F0083ECD3 /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = E90CB4A8254B8C3C0083ECD3 /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = E90CB4AF254B8C3C0083ECD3;
35 | remoteInfo = CleanSwiftExample;
36 | };
37 | E90CB4D2254B8C3F0083ECD3 /* PBXContainerItemProxy */ = {
38 | isa = PBXContainerItemProxy;
39 | containerPortal = E90CB4A8254B8C3C0083ECD3 /* Project object */;
40 | proxyType = 1;
41 | remoteGlobalIDString = E90CB4AF254B8C3C0083ECD3;
42 | remoteInfo = CleanSwiftExample;
43 | };
44 | /* End PBXContainerItemProxy section */
45 |
46 | /* Begin PBXFileReference section */
47 | E90CB4B0254B8C3C0083ECD3 /* CleanSwiftExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CleanSwiftExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
48 | E90CB4B3254B8C3C0083ECD3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
49 | E90CB4B5254B8C3C0083ECD3 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
50 | E90CB4B7254B8C3C0083ECD3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
51 | E90CB4BA254B8C3C0083ECD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
52 | E90CB4BC254B8C3F0083ECD3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
53 | E90CB4BF254B8C3F0083ECD3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
54 | E90CB4C1254B8C3F0083ECD3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
55 | E90CB4C6254B8C3F0083ECD3 /* CleanSwiftExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CleanSwiftExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
56 | E90CB4CA254B8C3F0083ECD3 /* CleanSwiftExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CleanSwiftExampleTests.swift; sourceTree = ""; };
57 | E90CB4CC254B8C3F0083ECD3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | E90CB4D1254B8C3F0083ECD3 /* CleanSwiftExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CleanSwiftExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
59 | E90CB4D5254B8C3F0083ECD3 /* CleanSwiftExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CleanSwiftExampleUITests.swift; sourceTree = ""; };
60 | E90CB4D7254B8C3F0083ECD3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
61 | E90CB4E7254B8C6C0083ECD3 /* LoginPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginPresenter.swift; sourceTree = ""; };
62 | E90CB4E9254B8C6C0083ECD3 /* LoginRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginRouter.swift; sourceTree = ""; };
63 | E90CB4EA254B8C6C0083ECD3 /* LoginModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginModels.swift; sourceTree = ""; };
64 | E90CB4EB254B8C6C0083ECD3 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; };
65 | E90CB4EC254B8C6C0083ECD3 /* LoginInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginInteractor.swift; sourceTree = ""; };
66 | E94DB10A254DFAC2009215FA /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; };
67 | E94DB121254E19A5009215FA /* LoginViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LoginViewController.storyboard; sourceTree = ""; };
68 | E94DB12A254E1AF1009215FA /* HomeViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = HomeViewController.storyboard; sourceTree = ""; };
69 | E94DB12F254E1B02009215FA /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; };
70 | /* End PBXFileReference section */
71 |
72 | /* Begin PBXFrameworksBuildPhase section */
73 | E90CB4AD254B8C3C0083ECD3 /* Frameworks */ = {
74 | isa = PBXFrameworksBuildPhase;
75 | buildActionMask = 2147483647;
76 | files = (
77 | );
78 | runOnlyForDeploymentPostprocessing = 0;
79 | };
80 | E90CB4C3254B8C3F0083ECD3 /* Frameworks */ = {
81 | isa = PBXFrameworksBuildPhase;
82 | buildActionMask = 2147483647;
83 | files = (
84 | );
85 | runOnlyForDeploymentPostprocessing = 0;
86 | };
87 | E90CB4CE254B8C3F0083ECD3 /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | /* End PBXFrameworksBuildPhase section */
95 |
96 | /* Begin PBXGroup section */
97 | E90CB4A7254B8C3C0083ECD3 = {
98 | isa = PBXGroup;
99 | children = (
100 | E90CB4B2254B8C3C0083ECD3 /* CleanSwiftExample */,
101 | E90CB4C9254B8C3F0083ECD3 /* CleanSwiftExampleTests */,
102 | E90CB4D4254B8C3F0083ECD3 /* CleanSwiftExampleUITests */,
103 | E90CB4B1254B8C3C0083ECD3 /* Products */,
104 | );
105 | sourceTree = "";
106 | };
107 | E90CB4B1254B8C3C0083ECD3 /* Products */ = {
108 | isa = PBXGroup;
109 | children = (
110 | E90CB4B0254B8C3C0083ECD3 /* CleanSwiftExample.app */,
111 | E90CB4C6254B8C3F0083ECD3 /* CleanSwiftExampleTests.xctest */,
112 | E90CB4D1254B8C3F0083ECD3 /* CleanSwiftExampleUITests.xctest */,
113 | );
114 | name = Products;
115 | sourceTree = "";
116 | };
117 | E90CB4B2254B8C3C0083ECD3 /* CleanSwiftExample */ = {
118 | isa = PBXGroup;
119 | children = (
120 | E94DB109254DFAA7009215FA /* Model */,
121 | E94DB10F254DFAD7009215FA /* Screens */,
122 | E90CB4B3254B8C3C0083ECD3 /* AppDelegate.swift */,
123 | E90CB4B5254B8C3C0083ECD3 /* SceneDelegate.swift */,
124 | E90CB4B7254B8C3C0083ECD3 /* ViewController.swift */,
125 | E90CB4B9254B8C3C0083ECD3 /* Main.storyboard */,
126 | E90CB4BC254B8C3F0083ECD3 /* Assets.xcassets */,
127 | E90CB4BE254B8C3F0083ECD3 /* LaunchScreen.storyboard */,
128 | E90CB4C1254B8C3F0083ECD3 /* Info.plist */,
129 | );
130 | path = CleanSwiftExample;
131 | sourceTree = "";
132 | };
133 | E90CB4C9254B8C3F0083ECD3 /* CleanSwiftExampleTests */ = {
134 | isa = PBXGroup;
135 | children = (
136 | E90CB4CA254B8C3F0083ECD3 /* CleanSwiftExampleTests.swift */,
137 | E90CB4CC254B8C3F0083ECD3 /* Info.plist */,
138 | );
139 | path = CleanSwiftExampleTests;
140 | sourceTree = "";
141 | };
142 | E90CB4D4254B8C3F0083ECD3 /* CleanSwiftExampleUITests */ = {
143 | isa = PBXGroup;
144 | children = (
145 | E90CB4D5254B8C3F0083ECD3 /* CleanSwiftExampleUITests.swift */,
146 | E90CB4D7254B8C3F0083ECD3 /* Info.plist */,
147 | );
148 | path = CleanSwiftExampleUITests;
149 | sourceTree = "";
150 | };
151 | E90CB4E6254B8C550083ECD3 /* Login */ = {
152 | isa = PBXGroup;
153 | children = (
154 | E94DB121254E19A5009215FA /* LoginViewController.storyboard */,
155 | E90CB4EB254B8C6C0083ECD3 /* LoginViewController.swift */,
156 | E90CB4EC254B8C6C0083ECD3 /* LoginInteractor.swift */,
157 | E90CB4E7254B8C6C0083ECD3 /* LoginPresenter.swift */,
158 | E90CB4EA254B8C6C0083ECD3 /* LoginModels.swift */,
159 | E90CB4E9254B8C6C0083ECD3 /* LoginRouter.swift */,
160 | );
161 | path = Login;
162 | sourceTree = "";
163 | };
164 | E94DB109254DFAA7009215FA /* Model */ = {
165 | isa = PBXGroup;
166 | children = (
167 | E94DB10A254DFAC2009215FA /* User.swift */,
168 | );
169 | path = Model;
170 | sourceTree = "";
171 | };
172 | E94DB10F254DFAD7009215FA /* Screens */ = {
173 | isa = PBXGroup;
174 | children = (
175 | E90CB4E6254B8C550083ECD3 /* Login */,
176 | E94DB129254E1AD3009215FA /* Home */,
177 | );
178 | path = Screens;
179 | sourceTree = "";
180 | };
181 | E94DB129254E1AD3009215FA /* Home */ = {
182 | isa = PBXGroup;
183 | children = (
184 | E94DB12A254E1AF1009215FA /* HomeViewController.storyboard */,
185 | E94DB12F254E1B02009215FA /* HomeViewController.swift */,
186 | );
187 | path = Home;
188 | sourceTree = "";
189 | };
190 | /* End PBXGroup section */
191 |
192 | /* Begin PBXNativeTarget section */
193 | E90CB4AF254B8C3C0083ECD3 /* CleanSwiftExample */ = {
194 | isa = PBXNativeTarget;
195 | buildConfigurationList = E90CB4DA254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExample" */;
196 | buildPhases = (
197 | E90CB4AC254B8C3C0083ECD3 /* Sources */,
198 | E90CB4AD254B8C3C0083ECD3 /* Frameworks */,
199 | E90CB4AE254B8C3C0083ECD3 /* Resources */,
200 | );
201 | buildRules = (
202 | );
203 | dependencies = (
204 | );
205 | name = CleanSwiftExample;
206 | productName = CleanSwiftExample;
207 | productReference = E90CB4B0254B8C3C0083ECD3 /* CleanSwiftExample.app */;
208 | productType = "com.apple.product-type.application";
209 | };
210 | E90CB4C5254B8C3F0083ECD3 /* CleanSwiftExampleTests */ = {
211 | isa = PBXNativeTarget;
212 | buildConfigurationList = E90CB4DD254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExampleTests" */;
213 | buildPhases = (
214 | E90CB4C2254B8C3F0083ECD3 /* Sources */,
215 | E90CB4C3254B8C3F0083ECD3 /* Frameworks */,
216 | E90CB4C4254B8C3F0083ECD3 /* Resources */,
217 | );
218 | buildRules = (
219 | );
220 | dependencies = (
221 | E90CB4C8254B8C3F0083ECD3 /* PBXTargetDependency */,
222 | );
223 | name = CleanSwiftExampleTests;
224 | productName = CleanSwiftExampleTests;
225 | productReference = E90CB4C6254B8C3F0083ECD3 /* CleanSwiftExampleTests.xctest */;
226 | productType = "com.apple.product-type.bundle.unit-test";
227 | };
228 | E90CB4D0254B8C3F0083ECD3 /* CleanSwiftExampleUITests */ = {
229 | isa = PBXNativeTarget;
230 | buildConfigurationList = E90CB4E0254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExampleUITests" */;
231 | buildPhases = (
232 | E90CB4CD254B8C3F0083ECD3 /* Sources */,
233 | E90CB4CE254B8C3F0083ECD3 /* Frameworks */,
234 | E90CB4CF254B8C3F0083ECD3 /* Resources */,
235 | );
236 | buildRules = (
237 | );
238 | dependencies = (
239 | E90CB4D3254B8C3F0083ECD3 /* PBXTargetDependency */,
240 | );
241 | name = CleanSwiftExampleUITests;
242 | productName = CleanSwiftExampleUITests;
243 | productReference = E90CB4D1254B8C3F0083ECD3 /* CleanSwiftExampleUITests.xctest */;
244 | productType = "com.apple.product-type.bundle.ui-testing";
245 | };
246 | /* End PBXNativeTarget section */
247 |
248 | /* Begin PBXProject section */
249 | E90CB4A8254B8C3C0083ECD3 /* Project object */ = {
250 | isa = PBXProject;
251 | attributes = {
252 | LastSwiftUpdateCheck = 1200;
253 | LastUpgradeCheck = 1200;
254 | TargetAttributes = {
255 | E90CB4AF254B8C3C0083ECD3 = {
256 | CreatedOnToolsVersion = 12.0.1;
257 | };
258 | E90CB4C5254B8C3F0083ECD3 = {
259 | CreatedOnToolsVersion = 12.0.1;
260 | TestTargetID = E90CB4AF254B8C3C0083ECD3;
261 | };
262 | E90CB4D0254B8C3F0083ECD3 = {
263 | CreatedOnToolsVersion = 12.0.1;
264 | TestTargetID = E90CB4AF254B8C3C0083ECD3;
265 | };
266 | };
267 | };
268 | buildConfigurationList = E90CB4AB254B8C3C0083ECD3 /* Build configuration list for PBXProject "CleanSwiftExample" */;
269 | compatibilityVersion = "Xcode 9.3";
270 | developmentRegion = en;
271 | hasScannedForEncodings = 0;
272 | knownRegions = (
273 | en,
274 | Base,
275 | );
276 | mainGroup = E90CB4A7254B8C3C0083ECD3;
277 | productRefGroup = E90CB4B1254B8C3C0083ECD3 /* Products */;
278 | projectDirPath = "";
279 | projectRoot = "";
280 | targets = (
281 | E90CB4AF254B8C3C0083ECD3 /* CleanSwiftExample */,
282 | E90CB4C5254B8C3F0083ECD3 /* CleanSwiftExampleTests */,
283 | E90CB4D0254B8C3F0083ECD3 /* CleanSwiftExampleUITests */,
284 | );
285 | };
286 | /* End PBXProject section */
287 |
288 | /* Begin PBXResourcesBuildPhase section */
289 | E90CB4AE254B8C3C0083ECD3 /* Resources */ = {
290 | isa = PBXResourcesBuildPhase;
291 | buildActionMask = 2147483647;
292 | files = (
293 | E94DB12B254E1AF1009215FA /* HomeViewController.storyboard in Resources */,
294 | E90CB4C0254B8C3F0083ECD3 /* LaunchScreen.storyboard in Resources */,
295 | E94DB122254E19A5009215FA /* LoginViewController.storyboard in Resources */,
296 | E90CB4BD254B8C3F0083ECD3 /* Assets.xcassets in Resources */,
297 | E90CB4BB254B8C3C0083ECD3 /* Main.storyboard in Resources */,
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | E90CB4C4254B8C3F0083ECD3 /* Resources */ = {
302 | isa = PBXResourcesBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | );
306 | runOnlyForDeploymentPostprocessing = 0;
307 | };
308 | E90CB4CF254B8C3F0083ECD3 /* Resources */ = {
309 | isa = PBXResourcesBuildPhase;
310 | buildActionMask = 2147483647;
311 | files = (
312 | );
313 | runOnlyForDeploymentPostprocessing = 0;
314 | };
315 | /* End PBXResourcesBuildPhase section */
316 |
317 | /* Begin PBXSourcesBuildPhase section */
318 | E90CB4AC254B8C3C0083ECD3 /* Sources */ = {
319 | isa = PBXSourcesBuildPhase;
320 | buildActionMask = 2147483647;
321 | files = (
322 | E90CB4ED254B8C6C0083ECD3 /* LoginPresenter.swift in Sources */,
323 | E90CB4F0254B8C6C0083ECD3 /* LoginModels.swift in Sources */,
324 | E90CB4EF254B8C6C0083ECD3 /* LoginRouter.swift in Sources */,
325 | E90CB4F1254B8C6C0083ECD3 /* LoginViewController.swift in Sources */,
326 | E90CB4B8254B8C3C0083ECD3 /* ViewController.swift in Sources */,
327 | E94DB130254E1B02009215FA /* HomeViewController.swift in Sources */,
328 | E90CB4B4254B8C3C0083ECD3 /* AppDelegate.swift in Sources */,
329 | E90CB4B6254B8C3C0083ECD3 /* SceneDelegate.swift in Sources */,
330 | E94DB10B254DFAC2009215FA /* User.swift in Sources */,
331 | E90CB4F2254B8C6C0083ECD3 /* LoginInteractor.swift in Sources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | E90CB4C2254B8C3F0083ECD3 /* Sources */ = {
336 | isa = PBXSourcesBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | E90CB4CB254B8C3F0083ECD3 /* CleanSwiftExampleTests.swift in Sources */,
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | E90CB4CD254B8C3F0083ECD3 /* Sources */ = {
344 | isa = PBXSourcesBuildPhase;
345 | buildActionMask = 2147483647;
346 | files = (
347 | E90CB4D6254B8C3F0083ECD3 /* CleanSwiftExampleUITests.swift in Sources */,
348 | );
349 | runOnlyForDeploymentPostprocessing = 0;
350 | };
351 | /* End PBXSourcesBuildPhase section */
352 |
353 | /* Begin PBXTargetDependency section */
354 | E90CB4C8254B8C3F0083ECD3 /* PBXTargetDependency */ = {
355 | isa = PBXTargetDependency;
356 | target = E90CB4AF254B8C3C0083ECD3 /* CleanSwiftExample */;
357 | targetProxy = E90CB4C7254B8C3F0083ECD3 /* PBXContainerItemProxy */;
358 | };
359 | E90CB4D3254B8C3F0083ECD3 /* PBXTargetDependency */ = {
360 | isa = PBXTargetDependency;
361 | target = E90CB4AF254B8C3C0083ECD3 /* CleanSwiftExample */;
362 | targetProxy = E90CB4D2254B8C3F0083ECD3 /* PBXContainerItemProxy */;
363 | };
364 | /* End PBXTargetDependency section */
365 |
366 | /* Begin PBXVariantGroup section */
367 | E90CB4B9254B8C3C0083ECD3 /* Main.storyboard */ = {
368 | isa = PBXVariantGroup;
369 | children = (
370 | E90CB4BA254B8C3C0083ECD3 /* Base */,
371 | );
372 | name = Main.storyboard;
373 | sourceTree = "";
374 | };
375 | E90CB4BE254B8C3F0083ECD3 /* LaunchScreen.storyboard */ = {
376 | isa = PBXVariantGroup;
377 | children = (
378 | E90CB4BF254B8C3F0083ECD3 /* Base */,
379 | );
380 | name = LaunchScreen.storyboard;
381 | sourceTree = "";
382 | };
383 | /* End PBXVariantGroup section */
384 |
385 | /* Begin XCBuildConfiguration section */
386 | E90CB4D8254B8C3F0083ECD3 /* Debug */ = {
387 | isa = XCBuildConfiguration;
388 | buildSettings = {
389 | ALWAYS_SEARCH_USER_PATHS = NO;
390 | CLANG_ANALYZER_NONNULL = YES;
391 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
392 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
393 | CLANG_CXX_LIBRARY = "libc++";
394 | CLANG_ENABLE_MODULES = YES;
395 | CLANG_ENABLE_OBJC_ARC = YES;
396 | CLANG_ENABLE_OBJC_WEAK = YES;
397 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
398 | CLANG_WARN_BOOL_CONVERSION = YES;
399 | CLANG_WARN_COMMA = YES;
400 | CLANG_WARN_CONSTANT_CONVERSION = YES;
401 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
402 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
403 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
404 | CLANG_WARN_EMPTY_BODY = YES;
405 | CLANG_WARN_ENUM_CONVERSION = YES;
406 | CLANG_WARN_INFINITE_RECURSION = YES;
407 | CLANG_WARN_INT_CONVERSION = YES;
408 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
409 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
410 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
412 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
413 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
414 | CLANG_WARN_STRICT_PROTOTYPES = YES;
415 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
416 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
417 | CLANG_WARN_UNREACHABLE_CODE = YES;
418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
419 | COPY_PHASE_STRIP = NO;
420 | DEBUG_INFORMATION_FORMAT = dwarf;
421 | ENABLE_STRICT_OBJC_MSGSEND = YES;
422 | ENABLE_TESTABILITY = YES;
423 | GCC_C_LANGUAGE_STANDARD = gnu11;
424 | GCC_DYNAMIC_NO_PIC = NO;
425 | GCC_NO_COMMON_BLOCKS = YES;
426 | GCC_OPTIMIZATION_LEVEL = 0;
427 | GCC_PREPROCESSOR_DEFINITIONS = (
428 | "DEBUG=1",
429 | "$(inherited)",
430 | );
431 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
432 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
433 | GCC_WARN_UNDECLARED_SELECTOR = YES;
434 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
435 | GCC_WARN_UNUSED_FUNCTION = YES;
436 | GCC_WARN_UNUSED_VARIABLE = YES;
437 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
438 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
439 | MTL_FAST_MATH = YES;
440 | ONLY_ACTIVE_ARCH = YES;
441 | SDKROOT = iphoneos;
442 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
443 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
444 | };
445 | name = Debug;
446 | };
447 | E90CB4D9254B8C3F0083ECD3 /* Release */ = {
448 | isa = XCBuildConfiguration;
449 | buildSettings = {
450 | ALWAYS_SEARCH_USER_PATHS = NO;
451 | CLANG_ANALYZER_NONNULL = YES;
452 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
453 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
454 | CLANG_CXX_LIBRARY = "libc++";
455 | CLANG_ENABLE_MODULES = YES;
456 | CLANG_ENABLE_OBJC_ARC = YES;
457 | CLANG_ENABLE_OBJC_WEAK = YES;
458 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
459 | CLANG_WARN_BOOL_CONVERSION = YES;
460 | CLANG_WARN_COMMA = YES;
461 | CLANG_WARN_CONSTANT_CONVERSION = YES;
462 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
463 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
464 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
465 | CLANG_WARN_EMPTY_BODY = YES;
466 | CLANG_WARN_ENUM_CONVERSION = YES;
467 | CLANG_WARN_INFINITE_RECURSION = YES;
468 | CLANG_WARN_INT_CONVERSION = YES;
469 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
470 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
471 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
472 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
473 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
474 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
475 | CLANG_WARN_STRICT_PROTOTYPES = YES;
476 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
477 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
478 | CLANG_WARN_UNREACHABLE_CODE = YES;
479 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
480 | COPY_PHASE_STRIP = NO;
481 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
482 | ENABLE_NS_ASSERTIONS = NO;
483 | ENABLE_STRICT_OBJC_MSGSEND = YES;
484 | GCC_C_LANGUAGE_STANDARD = gnu11;
485 | GCC_NO_COMMON_BLOCKS = YES;
486 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
487 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
488 | GCC_WARN_UNDECLARED_SELECTOR = YES;
489 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
490 | GCC_WARN_UNUSED_FUNCTION = YES;
491 | GCC_WARN_UNUSED_VARIABLE = YES;
492 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
493 | MTL_ENABLE_DEBUG_INFO = NO;
494 | MTL_FAST_MATH = YES;
495 | SDKROOT = iphoneos;
496 | SWIFT_COMPILATION_MODE = wholemodule;
497 | SWIFT_OPTIMIZATION_LEVEL = "-O";
498 | VALIDATE_PRODUCT = YES;
499 | };
500 | name = Release;
501 | };
502 | E90CB4DB254B8C3F0083ECD3 /* Debug */ = {
503 | isa = XCBuildConfiguration;
504 | buildSettings = {
505 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
506 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
507 | CODE_SIGN_STYLE = Automatic;
508 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
509 | INFOPLIST_FILE = CleanSwiftExample/Info.plist;
510 | LD_RUNPATH_SEARCH_PATHS = (
511 | "$(inherited)",
512 | "@executable_path/Frameworks",
513 | );
514 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExample;
515 | PRODUCT_NAME = "$(TARGET_NAME)";
516 | SWIFT_VERSION = 5.0;
517 | TARGETED_DEVICE_FAMILY = "1,2";
518 | };
519 | name = Debug;
520 | };
521 | E90CB4DC254B8C3F0083ECD3 /* Release */ = {
522 | isa = XCBuildConfiguration;
523 | buildSettings = {
524 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
525 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
526 | CODE_SIGN_STYLE = Automatic;
527 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
528 | INFOPLIST_FILE = CleanSwiftExample/Info.plist;
529 | LD_RUNPATH_SEARCH_PATHS = (
530 | "$(inherited)",
531 | "@executable_path/Frameworks",
532 | );
533 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExample;
534 | PRODUCT_NAME = "$(TARGET_NAME)";
535 | SWIFT_VERSION = 5.0;
536 | TARGETED_DEVICE_FAMILY = "1,2";
537 | };
538 | name = Release;
539 | };
540 | E90CB4DE254B8C3F0083ECD3 /* Debug */ = {
541 | isa = XCBuildConfiguration;
542 | buildSettings = {
543 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
544 | BUNDLE_LOADER = "$(TEST_HOST)";
545 | CODE_SIGN_STYLE = Automatic;
546 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
547 | INFOPLIST_FILE = CleanSwiftExampleTests/Info.plist;
548 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
549 | LD_RUNPATH_SEARCH_PATHS = (
550 | "$(inherited)",
551 | "@executable_path/Frameworks",
552 | "@loader_path/Frameworks",
553 | );
554 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExampleTests;
555 | PRODUCT_NAME = "$(TARGET_NAME)";
556 | SWIFT_VERSION = 5.0;
557 | TARGETED_DEVICE_FAMILY = "1,2";
558 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CleanSwiftExample.app/CleanSwiftExample";
559 | };
560 | name = Debug;
561 | };
562 | E90CB4DF254B8C3F0083ECD3 /* Release */ = {
563 | isa = XCBuildConfiguration;
564 | buildSettings = {
565 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
566 | BUNDLE_LOADER = "$(TEST_HOST)";
567 | CODE_SIGN_STYLE = Automatic;
568 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
569 | INFOPLIST_FILE = CleanSwiftExampleTests/Info.plist;
570 | IPHONEOS_DEPLOYMENT_TARGET = 14.0;
571 | LD_RUNPATH_SEARCH_PATHS = (
572 | "$(inherited)",
573 | "@executable_path/Frameworks",
574 | "@loader_path/Frameworks",
575 | );
576 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExampleTests;
577 | PRODUCT_NAME = "$(TARGET_NAME)";
578 | SWIFT_VERSION = 5.0;
579 | TARGETED_DEVICE_FAMILY = "1,2";
580 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CleanSwiftExample.app/CleanSwiftExample";
581 | };
582 | name = Release;
583 | };
584 | E90CB4E1254B8C3F0083ECD3 /* Debug */ = {
585 | isa = XCBuildConfiguration;
586 | buildSettings = {
587 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
588 | CODE_SIGN_STYLE = Automatic;
589 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
590 | INFOPLIST_FILE = CleanSwiftExampleUITests/Info.plist;
591 | LD_RUNPATH_SEARCH_PATHS = (
592 | "$(inherited)",
593 | "@executable_path/Frameworks",
594 | "@loader_path/Frameworks",
595 | );
596 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExampleUITests;
597 | PRODUCT_NAME = "$(TARGET_NAME)";
598 | SWIFT_VERSION = 5.0;
599 | TARGETED_DEVICE_FAMILY = "1,2";
600 | TEST_TARGET_NAME = CleanSwiftExample;
601 | };
602 | name = Debug;
603 | };
604 | E90CB4E2254B8C3F0083ECD3 /* Release */ = {
605 | isa = XCBuildConfiguration;
606 | buildSettings = {
607 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
608 | CODE_SIGN_STYLE = Automatic;
609 | DEVELOPMENT_TEAM = MJB4D8DJZ5;
610 | INFOPLIST_FILE = CleanSwiftExampleUITests/Info.plist;
611 | LD_RUNPATH_SEARCH_PATHS = (
612 | "$(inherited)",
613 | "@executable_path/Frameworks",
614 | "@loader_path/Frameworks",
615 | );
616 | PRODUCT_BUNDLE_IDENTIFIER = com.SweetAppsStudio.CleanSwiftExampleUITests;
617 | PRODUCT_NAME = "$(TARGET_NAME)";
618 | SWIFT_VERSION = 5.0;
619 | TARGETED_DEVICE_FAMILY = "1,2";
620 | TEST_TARGET_NAME = CleanSwiftExample;
621 | };
622 | name = Release;
623 | };
624 | /* End XCBuildConfiguration section */
625 |
626 | /* Begin XCConfigurationList section */
627 | E90CB4AB254B8C3C0083ECD3 /* Build configuration list for PBXProject "CleanSwiftExample" */ = {
628 | isa = XCConfigurationList;
629 | buildConfigurations = (
630 | E90CB4D8254B8C3F0083ECD3 /* Debug */,
631 | E90CB4D9254B8C3F0083ECD3 /* Release */,
632 | );
633 | defaultConfigurationIsVisible = 0;
634 | defaultConfigurationName = Release;
635 | };
636 | E90CB4DA254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExample" */ = {
637 | isa = XCConfigurationList;
638 | buildConfigurations = (
639 | E90CB4DB254B8C3F0083ECD3 /* Debug */,
640 | E90CB4DC254B8C3F0083ECD3 /* Release */,
641 | );
642 | defaultConfigurationIsVisible = 0;
643 | defaultConfigurationName = Release;
644 | };
645 | E90CB4DD254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExampleTests" */ = {
646 | isa = XCConfigurationList;
647 | buildConfigurations = (
648 | E90CB4DE254B8C3F0083ECD3 /* Debug */,
649 | E90CB4DF254B8C3F0083ECD3 /* Release */,
650 | );
651 | defaultConfigurationIsVisible = 0;
652 | defaultConfigurationName = Release;
653 | };
654 | E90CB4E0254B8C3F0083ECD3 /* Build configuration list for PBXNativeTarget "CleanSwiftExampleUITests" */ = {
655 | isa = XCConfigurationList;
656 | buildConfigurations = (
657 | E90CB4E1254B8C3F0083ECD3 /* Debug */,
658 | E90CB4E2254B8C3F0083ECD3 /* Release */,
659 | );
660 | defaultConfigurationIsVisible = 0;
661 | defaultConfigurationName = Release;
662 | };
663 | /* End XCConfigurationList section */
664 | };
665 | rootObject = E90CB4A8254B8C3C0083ECD3 /* Project object */;
666 | }
667 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample.xcodeproj/project.xcworkspace/xcuserdata/yoni.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yonivav/CleanSwiftTemplates/8f18af64a0bb67f4ac2406994bd60322db7f876c/CleanSwiftExample/CleanSwiftExample.xcodeproj/project.xcworkspace/xcuserdata/yoni.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample.xcodeproj/xcuserdata/yoni.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | CleanSwiftExample.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Base.lproj/LaunchScreen.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 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Base.lproj/Main.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 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 | UISceneStoryboardFile
37 | Main
38 |
39 |
40 |
41 |
42 | UIApplicationSupportsIndirectInputEvents
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Model/Result.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Result.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/31/20.
6 | //
7 |
8 | import Foundation
9 |
10 | enum Result {
11 | case success(T)
12 | case failure(Error)
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Model/User.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserModel.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/31/20.
6 | //
7 |
8 | import Foundation
9 |
10 | struct User: Codable {
11 | let name: String
12 | let id: String
13 | let firstName: String
14 | let lastName: String
15 | let email: String
16 | let phone_number: String
17 | let age: Int
18 | let facebookLink: String
19 | let token: String
20 | let isInRelationship: Bool
21 | }
22 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Home/HomeViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Home/HomeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeViewController.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 11/1/20.
6 | //
7 |
8 | import Foundation
9 | import UIKit
10 |
11 | class HomeViewController: UIViewController {}
12 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginInteractor.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | // Copyright (c) 2020 ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol LoginBusinessLogic {
16 | func login(request: Login.Login.Request)
17 | }
18 |
19 | class LoginInteractor: LoginBusinessLogic {
20 | var presenter: LoginPresentationLogic?
21 |
22 | // MARK: Login (and send response to LoginPresenter)
23 |
24 | func login(request: Login.Login.Request) {
25 |
26 | // for our example, lets build a user which this Interactor received from server
27 | let userResponse = User(name: "Capitan Jack Sparrow",
28 | id: "135735",
29 | firstName: "Jacky",
30 | lastName: "Sparrow",
31 | email: "jacky.sparrow@piratesOfTheCaribbean.com",
32 | phone_number: "+972-549-424-420",
33 | age: 31,
34 | facebookLink: "https://www.facebook.com/CaptainJackSparrow",
35 | token: "af47e509r678fuyhjv",
36 | isInRelationship: false)
37 |
38 | let response = Login.Login.Response(user: userResponse)
39 | presenter?.presentLogin(response: response)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginModels.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | // Copyright (c) 2020 ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | enum Login
16 | {
17 | // MARK: Use cases
18 |
19 | enum Login {
20 | struct Request {
21 | let username, password: String
22 | }
23 |
24 | struct Response{
25 | let user: User
26 | }
27 |
28 | struct ViewModelSuccess{
29 | let username: String
30 | let age: Int
31 | }
32 |
33 | struct ViewModelFailure{
34 | let errorMessage: String
35 | }
36 | }
37 | }
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginPresenter.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | // Copyright (c) 2020 ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol LoginPresentationLogic {
16 | func presentLogin(response: Login.Login.Response)
17 | }
18 |
19 | class LoginPresenter: LoginPresentationLogic {
20 | weak var viewController: LoginDisplayLogic?
21 |
22 | // MARK: Parse and calc respnse from LoginInteractor and send simple view model to LoginViewController to be displayed
23 |
24 | func presentLogin(response: Login.Login.Response) {
25 | let username = response.user.name
26 | let age = response.user.age
27 | let viewModel = Login.Login.ViewModelSuccess(username: username, age: age)
28 | viewController?.displayUser(viewModel: viewModel)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginRouter.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | // Copyright (c) 2020 ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol LoginRoutingLogic {
16 | func routeToNextScreen(segue: UIStoryboardSegue?)
17 | }
18 |
19 | class LoginRouter: NSObject, LoginRoutingLogic {
20 | weak var viewController: LoginViewController?
21 |
22 | // MARK: Routing (navigating to other screens)
23 |
24 | func routeToNextScreen(segue: UIStoryboardSegue?) {
25 | // if let segue = segue {
26 | // let destinationVC = segue.destination as! SomewhereViewController
27 | // var destinationDS = destinationVC.router!.dataStore!
28 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
29 | // } else {
30 | // let storyboard = UIStoryboard(name: "Main", bundle: nil)
31 | // let destinationVC = storyboard.instantiateViewController(withIdentifier: "SomewhereViewController") as! SomewhereViewController
32 | // var destinationDS = destinationVC.router!.dataStore!
33 | // passDataToSomewhere(source: dataStore!, destination: &destinationDS)
34 | // navigateToSomewhere(source: viewController!, destination: destinationVC)
35 | // }
36 | }
37 |
38 | // MARK: Navigation to other screen
39 |
40 | // func navigateToSomewhere(source: LoginViewController, destination: SomewhereViewController) {
41 | // source.show(destination, sender: nil)
42 | // }
43 |
44 | // MARK: Passing data to other screen
45 |
46 | // func passDataToSomewhere(source: LoginDataStore, destination: inout SomewhereDataStore) {
47 | // destination.name = source.name
48 | // }
49 | }
50 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginViewController.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/Screens/Login/LoginViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginViewController.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | // Copyright (c) 2020 ___ORGANIZATIONNAME___. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift Xcode Templates so
9 | // you can apply clean architecture to your iOS and Mac projects,
10 | // see http://clean-swift.com
11 | //
12 |
13 | import UIKit
14 |
15 | protocol LoginDisplayLogic: class
16 | {
17 | func displayUser(viewModel: Login.Login.ViewModelSuccess)
18 | func displayFailure(viewModel: Login.Login.ViewModelFailure)
19 | }
20 |
21 | class LoginViewController: UIViewController, LoginDisplayLogic {
22 |
23 | private enum Segue: String {
24 | case homeSegue
25 | }
26 |
27 | var interactor: LoginBusinessLogic?
28 | var router: (NSObjectProtocol & LoginRoutingLogic)?
29 |
30 | // MARK: Object lifecycle
31 |
32 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
33 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
34 | modalPresentationStyle = .fullScreen
35 | setup()
36 | }
37 |
38 | required init?(coder aDecoder: NSCoder) {
39 | super.init(coder: aDecoder)
40 | modalPresentationStyle = .fullScreen
41 | setup()
42 | }
43 |
44 | // MARK: - Setup Clean Code Design Pattern
45 |
46 | private func setup() {
47 | let viewController = self
48 | let interactor = LoginInteractor()
49 | let presenter = LoginPresenter()
50 | let router = LoginRouter()
51 | viewController.interactor = interactor
52 | viewController.router = router
53 | interactor.presenter = presenter
54 | presenter.viewController = viewController
55 | router.viewController = viewController
56 | }
57 |
58 | //MARK: - receive events from UI
59 |
60 | @IBAction func loginButtonTapped(_ sender: Any) {
61 | login()
62 | }
63 |
64 | // MARK: - request data from LoginInteractor
65 |
66 | func login() {
67 | let request = Login.Login.Request(username: "Captain Jack Sparrow", password: "123456")
68 | interactor?.login(request: request)
69 | }
70 |
71 | // MARK: - display view model from LoginPresenter
72 |
73 | func displayUser(viewModel: Login.Login.ViewModelSuccess) {
74 | performSegue(withIdentifier: Segue.homeSegue.rawValue, sender: self)
75 | }
76 |
77 | func displayFailure(viewModel: Login.Login.ViewModelFailure) {
78 | // display error message
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExample/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // CleanSwiftExample
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | //
7 |
8 | import UIKit
9 |
10 | class ViewController: UIViewController {
11 |
12 | let loginViewController = LoginViewController()
13 |
14 | override func viewDidAppear(_ animated: Bool) {
15 | super.viewDidAppear(animated)
16 |
17 | guard let storyboard = storyboard else { return }
18 |
19 | let loginViewController = storyboard.instantiateViewController(identifier: "loginSegue")
20 | present(loginViewController, animated: false)
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExampleTests/CleanSwiftExampleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CleanSwiftExampleTests.swift
3 | // CleanSwiftExampleTests
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | //
7 |
8 | import XCTest
9 | @testable import CleanSwiftExample
10 |
11 | class CleanSwiftExampleTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | }
25 |
26 | func testPerformanceExample() throws {
27 | // This is an example of a performance test case.
28 | self.measure {
29 | // Put the code you want to measure the time of here.
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExampleUITests/CleanSwiftExampleUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CleanSwiftExampleUITests.swift
3 | // CleanSwiftExampleUITests
4 | //
5 | // Created by Yoni Vizel on 10/30/20.
6 | //
7 |
8 | import XCTest
9 |
10 | class CleanSwiftExampleUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/CleanSwiftExample/CleanSwiftExampleUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 yonivav
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 | 
2 | # CleanSwiftTemplates
3 | Clean Swift (a.k.a VIP) is Uncle Bob’s Clean Architecture applied to iOS and Mac projects. In the 'Clean Swift' folder, you can find a convenience template to add a new Xcode. In 'CleanSwiftExample' you can see a basic example.
4 |
5 | # Installation
6 | 1. Download the 'Clean Swift' folder from this project
7 | 2. In Finder Mac app: open folder (⌘+⇧+G): ~/Library/Developer/Xcode/Templates/
8 | 3. Open File Templates and paste the templates. It should look like this:
9 | 
10 | 4. Finish
11 |
12 |
13 | ## Example usage
14 | Lets say we want to add a login screen to our application. It will receive input from the user, which will be validated, and finally, it will display a success or failure response.
15 | For doing that please do:
16 | 1. Click on 'add new file' in Xcode, and click Next
17 |
18 | 
19 |
20 | 2. In your template list go down and choose 'Scene' under the 'Clean Swift' section
21 |
22 | 
23 |
24 | 3. type 'Login' for your new scene name. It should inherit from UIViewController.
25 |
26 | 
27 |
28 | You should see that all 6 files were added to your project
29 |
30 | 
31 |
32 | Finally, let's write some code!
33 |
34 | The flow should look like this:
35 | 1. LoginViewController needs to request an interactor to log in, with a username and password.
36 | Therefore, LoginViewInteractor should conform to a business logic protocol:
37 | ```
38 | protocol LoginBusinessLogic {
39 | func login(request: Login.Something.Request)
40 | }
41 | ```
42 | 2. LoginInteractor can validate this data in DB or network (NetworkWorker) and will answer it to LoginPresentor.
43 | Therefore, LoginViewPresenter should conform to a presentation logic protocol:
44 | ```
45 | protocol LoginPresentationLogic {
46 | func presentLogin(response: Login.Login.Response)
47 | }
48 | ```
49 | Its not too long or complicated, so LoginWorker unneeded and can be delete.
50 |
51 | 3. LoginPresneter will parse and process the response, and send to the view controller a simple straight forward data:
52 | Therefore, LoginViewController should conform to a display logic protocol:
53 | ```protocol LoginDisplayLogic: class
54 | {
55 | func displayUser(viewModel: Login.Something.ViewModeSuccess)
56 | func displayError(viewModel: Login.Something.ViewModeFailure)
57 | }
58 | ```
59 |
60 | The model part is like that:
61 | enum Something {
62 | ```
63 | // MARK: Use cases
64 | enum Login
65 | {
66 | // MARK: Use cases
67 |
68 | enum Login {
69 | struct Request {
70 | let username, password: String
71 | }
72 |
73 | struct Response{
74 | let user: User
75 | }
76 |
77 | struct ViewModelSuccess{
78 | let username: String
79 | let age: Int
80 | }
81 |
82 | struct ViewModelFailure{
83 | let errorMessage: String
84 | }
85 | }
86 | }
87 | ```
88 |
89 | 4. If a user log in successfully, LoginViewController will inform LoginRouter to move to another screen.
90 | Therefore, LoginRouter should conform to a routing logic protocol:
91 | ```
92 | protocol LoginRoutingLogic {
93 | func routeToNextScreen(segue: UIStoryboardSegue?)
94 | }
95 | ```
96 |
97 | ## Demo
98 | Open the CleanSwiftTemplatesExample project in Xcode to see the Login scenario as described in the above example.
99 |
100 |
101 | # About Clean Swift
102 | A very good explanation:
103 |
104 | https://zonneveld.dev/the-clean-swift-architecture-explained/
105 |
106 | and also:
107 |
108 | https://clean-swift.com/clean-swift-ios-architecture/
109 |
110 | https://sudonull.com/post/14437-Clean-swift-architecture-as-an-alternative-to-VIPER
111 |
112 | https://medium.com/dev-genius/clean-swift-vip-with-example-6f6e643a1a01
113 |
114 |
115 | In short:
116 | ### Structure
117 | The purpose of a Clean Swift design pattern is to separate the responsibilities of different entities for clarity and testability. Together, these entities form what we call scenes. Each family can operate independently using only the components within that family.
118 | The components of each family may include the following:
119 | * View Controller (with .xib or .storyboard file)
120 | * Interactor
121 | * Presenter
122 | * Model
123 | * (optional) Router
124 | * (optional) Worker
125 |
126 | ### The VIP cycle
127 | The Clean Swift architecture use a VIP cycle to help you separate logic in your application. The VIP cycle consists of a ViewController, Interactor, and a Presenter. All classes are responsible for some logic. The ViewController is responsible for the display logic, the Interactor is responsible for the business logic and the Presenter is responsible for the presentation logic.
128 |
129 | The ViewController is the first class where the action is triggered. The class is responsible for managing the views in the ViewController. In the ViewController, all outlets and IBAction functions should be listed.
130 | As soon as an action in the ViewController starts, the ViewController will pass that action to the Interactor. The Interactor is the class where all use cases should be implemented. By doing this, the Interactor is the class that contains all the business logic. This is a huge benefit when writing unit tests because when testing all interactors, all the business logic in your app is tested.
131 | The Interactor is responsible for handling the request and will return an object to the Presenter. The Presenter is the class that is responsible for presenting the object which is generated by the Interactor. The Presenter will parse that object to a ViewModel object and return an object to the ViewController to display.
132 | Using the Clean Swift architecture, you know exactly which logic should be located in which class. This makes your code more maintainable because when you need to solve a bug or want to add more functionalities, you know exactly where in your code the change should be made.
133 |
134 | ### Model
135 | During the VIP cycle, each class will add a data object when requesting an action from the other class in the cycle. When the ViewController asks the interactor to request an action from the Interactor, the ViewController will add a ‘Request’ object. This object contains all the data the interactor needs to do the business logic.
136 | The Interactor will handle the request. Once the data has been processed, it will return a ‘Response’ object to the Presenter. The Presenter will parse the data which is needed for a ‘ViewModel’ object, which will be sent to the ViewController. When the ViewModel is received by the ViewController, the ViewController only needs to update the UI elements with the data in the ViewModel.
137 |
138 |
139 | ### Router
140 | There may be situations in your app where the ViewController will present another ViewController. In Clean Swift, navigating between ViewControllers is done by a Router.
141 | If there are navigation options available for the ViewController, a Router class is added to the ViewController. The Router class contains all the navigation options where that specific ViewController can navigate through. By doing that, almost each VIP cycle will have a Router, which makes it clear what navigation options a ViewController has.
142 | A Presentor is responsible for the presentation logic. When a screen transition take place, the ViewController needs to ask this to the Interactor and then the Interactor needs to ask this to the Presentor. From there, the Presentor will decide that the ViewController may route to the next ViewController using the Router.
143 |
144 |
145 | ### Worker
146 | When having all business logic located in the Interactor, there may happen a situation where the Interactor will be a very large class. To prevent this, an Interactor can make use of multiple workers. A Worker is a helper of the Interactor, which can help receive data.
147 | A Worker is responsible for creating objects and doing network calls. Besides that, a Worker can be use to implement Third Party SDKs in your application. For example, if you use Alamofire for network requests, but do all the network requests in workers, the Alamofire SDK only needs to be imported into the worker.
148 | Workers must be generic, which means multiple interactors can use them if needed to handle data.
149 |
150 |
151 | # Contact
152 | Yoni Vizel
153 |
154 | https://github.com/yonivav
155 |
156 |
157 | # License
158 | Inspired from [this template](https://github.com/oluckyman/CleanSwift). CleanSwiftTemplates is available under the MIT license. See the LICENSE file for more info.
159 |
--------------------------------------------------------------------------------