├── .gitignore
├── CHANGELOG.md
├── Clean Swift HELM
├── Configurator.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Configurator.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___Configurator.swift
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ └── ___FILEBASENAME___ViewController.swift
│ ├── UITableViewController
│ │ ├── ___FILEBASENAME___Configurator.swift
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ └── ___FILEBASENAME___ViewController.swift
│ └── UIViewController
│ │ ├── ___FILEBASENAME___Configurator.swift
│ │ ├── ___FILEBASENAME___Interactor.swift
│ │ ├── ___FILEBASENAME___Models.swift
│ │ ├── ___FILEBASENAME___Presenter.swift
│ │ ├── ___FILEBASENAME___Router.swift
│ │ └── ___FILEBASENAME___ViewController.swift
├── Store.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── TemplateInfo.plist
│ └── ___FILEBASENAME___Store.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
├── Example
├── .gitignore
├── Cartfile
├── Cartfile.resolved
├── Example.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── Example
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── Common
│ │ └── SerializableUtils.swift
│ ├── Info.plist
│ ├── Models
│ │ ├── Name.swift
│ │ └── User.swift
│ ├── Scenes
│ │ ├── UserDetail
│ │ │ ├── UserDetailConfigurator.swift
│ │ │ ├── UserDetailInteractor.swift
│ │ │ ├── UserDetailModels.swift
│ │ │ ├── UserDetailPresenter.swift
│ │ │ ├── UserDetailRouter.swift
│ │ │ ├── UserDetailViewController+TableView.swift
│ │ │ └── UserDetailViewController.swift
│ │ └── UserList
│ │ │ ├── UI
│ │ │ ├── UserTableViewCell.swift
│ │ │ └── UserTableViewCell.xib
│ │ │ ├── UserListConfigurator.swift
│ │ │ ├── UserListInteractor.swift
│ │ │ ├── UserListModels.swift
│ │ │ ├── UserListPresenter.swift
│ │ │ ├── UserListRouter.swift
│ │ │ ├── UserListViewController+TableView.swift
│ │ │ ├── UserListViewController.swift
│ │ │ └── UserListWorker.swift
│ └── Services
│ │ ├── Mappers
│ │ ├── Name+Network.swift
│ │ └── User+Network.swift
│ │ └── Stores
│ │ ├── Definitions
│ │ └── UserStore.swift
│ │ └── Network
│ │ ├── Router
│ │ └── UserNetworkRouter.swift
│ │ └── UserNetworkStore.swift
└── cartupdate.sh
├── LICENSE
├── Makefile
├── README.md
├── Snippets
└── clean-swift-use-case.codesnippet
├── VERSION
└── configure
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 | *.xcodeproj/project.xcworkspace/xcuserdata/
20 |
21 | ## Other
22 | *.moved-aside
23 | *.xccheckout
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | # Pods/
47 |
48 | # For freaks who want to look like Android Developers
49 | .idea/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | #idea for the freaks who want to look like Android developers
59 | .idea
60 | # fastlane
61 | #
62 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
63 | # screenshots whenever they are needed.
64 | # For more information about the recommended setup visit:
65 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
66 |
67 | fastlane/report.xml
68 | fastlane/screenshots
69 | .githelm
70 | .gitpublic
71 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | ## 1.1.2
6 |
7 | - Added @testable import to unit test files
8 | - Fixed bug to get main bundle in view controller unit test setup
9 |
10 | ## 1.1.1
11 |
12 | - Added missing router input protocol conformance to router template
13 |
14 | ## 1.1.0
15 |
16 | - Added **Unit Tests** template to generate XCTest unit test files for
17 | - View controller
18 | - Interactor
19 | - Presenter
20 | - Worker
21 |
22 | ## 1.0.0
23 |
24 | - Added the **Scene** template to generate the following Clean Swift components:
25 | - View Controller
26 | - Interactor
27 | - Presenter
28 | - Router
29 | - Worker
30 | - Models
31 | - Configurator
32 | - These components can also be generated individually.
33 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Configurator.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Configurator.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Configurator.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Configurator.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Configurator.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyScene
7 | Description
8 | This generates a new configurator to connect the view controller, interactor, presenter, and router. You should not need to modify it.
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___Configurator
38 | Description
39 | The configurator name
40 | Identifier
41 | configuratorName
42 | Name
43 | Configurator 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 configurator to connect the view controller, interactor, presenter, and router. You should not need to modify it.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Configurator.xctemplate/___FILEBASENAME___Configurator.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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___ViewControllerOutput, ___VARIABLE_sceneName___RouterDataSource, ___VARIABLE_sceneName___RouterDataDestination {
16 | }
17 |
18 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___InteractorOutput {
19 | }
20 |
21 | class ___VARIABLE_sceneName___Configurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = ___VARIABLE_sceneName___Configurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: ___VARIABLE_sceneName___ViewController) {
31 |
32 | let presenter = ___VARIABLE_sceneName___Presenter()
33 | presenter.output = viewController
34 |
35 | let interactor = ___VARIABLE_sceneName___Interactor()
36 | interactor.output = presenter
37 |
38 | let router = ___VARIABLE_sceneName___Router(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Interactor.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Interactor.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Interactor.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Interactor.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 7
56 | Summary
57 | This generates a new interactor using Uncle Bob's clean architecture. Your business logic goes here.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___InteractorInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___InteractorOutput {
16 |
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataSource {
20 |
21 | }
22 |
23 | protocol ___VARIABLE_sceneName___DataDestination {
24 |
25 | }
26 |
27 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___InteractorInput, ___VARIABLE_sceneName___DataSource, ___VARIABLE_sceneName___DataDestination {
28 |
29 | var output: ___VARIABLE_sceneName___InteractorOutput?
30 |
31 | // MARK: Business logic
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Models.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Models.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Models.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Models.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 3
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 HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 | //
11 | // Type "usecase" for some magic!
12 |
13 | struct ___VARIABLE_sceneName___Scene {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Presenter.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Presenter.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Presenter.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Presenter.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 6
56 | Summary
57 | This generates a new presenter using Uncle Bob's clean architecture. Your presentation logic goes here.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___PresenterInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___PresenterOutput: class {
16 |
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
20 |
21 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Router.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Router.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Router.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Router.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 5
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 HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___RouterInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___RouterDataSource: class {
18 |
19 | }
20 |
21 | protocol ___VARIABLE_sceneName___RouterDataDestination: class {
22 |
23 | }
24 |
25 | class ___VARIABLE_sceneName___Router: ___VARIABLE_sceneName___RouterInput {
26 |
27 | weak var viewController: ___VARIABLE_sceneName___ViewController!
28 | weak private var dataSource: ___VARIABLE_sceneName___RouterDataSource!
29 | weak var dataDestination: ___VARIABLE_sceneName___RouterDataDestination!
30 |
31 | init(viewController: ___VARIABLE_sceneName___ViewController, dataSource: ___VARIABLE_sceneName___RouterDataSource, dataDestination: ___VARIABLE_sceneName___RouterDataDestination) {
32 | self.viewController = viewController
33 | self.dataSource = dataSource
34 | self.dataDestination = dataDestination
35 | }
36 |
37 | // MARK: Navigation
38 |
39 | // MARK: Communication
40 |
41 | func passDataToNextScene(for segue: UIStoryboardSegue) {
42 | // NOTE: Teach the router which scenes it can communicate with
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Scene.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Scene.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Scene.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Scene.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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___Models
108 | Description
109 | The model file name
110 | Identifier
111 | modelFileName
112 | Name
113 | Model File Name:
114 | Required
115 |
116 | Type
117 | static
118 |
119 |
120 | Default
121 | UIViewController
122 | Description
123 | What view controller class to subclass for the new scene
124 | FallbackHeader
125 | #import <UIKit/UIKit.h>
126 | Identifier
127 | viewControllerSubclass
128 | Name
129 | Subclass of:
130 | NotPersisted
131 |
132 | Required
133 | YES
134 | Type
135 | class
136 | Values
137 |
138 | UIViewController
139 | UITableViewController
140 | UICollectionViewController
141 |
142 |
143 |
144 | Platforms
145 |
146 | com.apple.platform.iphoneos
147 |
148 | SortOrder
149 | 9
150 | Summary
151 | This generates a new scene using Uncle Bob's clean architecture.
152 |
153 |
154 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Scene.xctemplate/UICollectionViewController/___FILEBASENAME___Configurator.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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___ViewControllerOutput, ___VARIABLE_sceneName___RouterDataSource, ___VARIABLE_sceneName___RouterDataDestination {
16 | }
17 |
18 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___InteractorOutput {
19 | }
20 |
21 | class ___VARIABLE_sceneName___Configurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = ___VARIABLE_sceneName___Configurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: ___VARIABLE_sceneName___ViewController) {
31 |
32 | let presenter = ___VARIABLE_sceneName___Presenter()
33 | presenter.output = viewController
34 |
35 | let interactor = ___VARIABLE_sceneName___Interactor()
36 | interactor.output = presenter
37 |
38 | let router = ___VARIABLE_sceneName___Router(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___InteractorInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___InteractorOutput {
16 |
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataSource {
20 |
21 | }
22 |
23 | protocol ___VARIABLE_sceneName___DataDestination {
24 |
25 | }
26 |
27 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___InteractorInput, ___VARIABLE_sceneName___DataSource, ___VARIABLE_sceneName___DataDestination {
28 |
29 | var output: ___VARIABLE_sceneName___InteractorOutput?
30 |
31 | // MARK: Business logic
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 | //
11 | // Type "usecase" for some magic!
12 |
13 | struct ___VARIABLE_sceneName___Scene {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___PresenterInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___PresenterOutput: class {
16 |
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
20 |
21 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___RouterInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___RouterDataSource: class {
18 |
19 | }
20 |
21 | protocol ___VARIABLE_sceneName___RouterDataDestination: class {
22 |
23 | }
24 |
25 | class ___VARIABLE_sceneName___Router: ___VARIABLE_sceneName___RouterInput {
26 |
27 | weak var viewController: ___VARIABLE_sceneName___ViewController!
28 | weak private var dataSource: ___VARIABLE_sceneName___RouterDataSource!
29 | weak var dataDestination: ___VARIABLE_sceneName___RouterDataDestination!
30 |
31 | init(viewController: ___VARIABLE_sceneName___ViewController, dataSource: ___VARIABLE_sceneName___RouterDataSource, dataDestination: ___VARIABLE_sceneName___RouterDataDestination) {
32 | self.viewController = viewController
33 | self.dataSource = dataSource
34 | self.dataDestination = dataDestination
35 | }
36 |
37 | // MARK: Navigation
38 |
39 | // MARK: Communication
40 |
41 | func passDataToNextScene(for segue: UIStoryboardSegue) {
42 | // NOTE: Teach the router which scenes it can communicate with
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UICollectionViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Scene.xctemplate/UITableViewController/___FILEBASENAME___Configurator.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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___ViewControllerOutput, ___VARIABLE_sceneName___RouterDataSource, ___VARIABLE_sceneName___RouterDataDestination {
16 | }
17 |
18 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___InteractorOutput {
19 | }
20 |
21 | class ___VARIABLE_sceneName___Configurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = ___VARIABLE_sceneName___Configurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: ___VARIABLE_sceneName___ViewController) {
31 |
32 | let presenter = ___VARIABLE_sceneName___Presenter()
33 | presenter.output = viewController
34 |
35 | let interactor = ___VARIABLE_sceneName___Interactor()
36 | interactor.output = presenter
37 |
38 | let router = ___VARIABLE_sceneName___Router(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___InteractorInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___InteractorOutput {
16 |
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataSource {
20 |
21 | }
22 |
23 | protocol ___VARIABLE_sceneName___DataDestination {
24 |
25 | }
26 |
27 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___InteractorInput, ___VARIABLE_sceneName___DataSource, ___VARIABLE_sceneName___DataDestination {
28 |
29 | var output: ___VARIABLE_sceneName___InteractorOutput?
30 |
31 | // MARK: Business logic
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 | //
11 | // Type "usecase" for some magic!
12 |
13 | struct ___VARIABLE_sceneName___Scene {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___PresenterInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___PresenterOutput: class {
16 |
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
20 |
21 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___RouterInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___RouterDataSource: class {
18 |
19 | }
20 |
21 | protocol ___VARIABLE_sceneName___RouterDataDestination: class {
22 |
23 | }
24 |
25 | class ___VARIABLE_sceneName___Router: ___VARIABLE_sceneName___RouterInput {
26 |
27 | weak var viewController: ___VARIABLE_sceneName___ViewController!
28 | weak private var dataSource: ___VARIABLE_sceneName___RouterDataSource!
29 | weak var dataDestination: ___VARIABLE_sceneName___RouterDataDestination!
30 |
31 | init(viewController: ___VARIABLE_sceneName___ViewController, dataSource: ___VARIABLE_sceneName___RouterDataSource, dataDestination: ___VARIABLE_sceneName___RouterDataDestination) {
32 | self.viewController = viewController
33 | self.dataSource = dataSource
34 | self.dataDestination = dataDestination
35 | }
36 |
37 | // MARK: Navigation
38 |
39 | // MARK: Communication
40 |
41 | func passDataToNextScene(for segue: UIStoryboardSegue) {
42 | // NOTE: Teach the router which scenes it can communicate with
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UITableViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Scene.xctemplate/UIViewController/___FILEBASENAME___Configurator.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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___ViewControllerOutput, ___VARIABLE_sceneName___RouterDataSource, ___VARIABLE_sceneName___RouterDataDestination {
16 | }
17 |
18 | extension ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___InteractorOutput {
19 | }
20 |
21 | class ___VARIABLE_sceneName___Configurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = ___VARIABLE_sceneName___Configurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: ___VARIABLE_sceneName___ViewController) {
31 |
32 | let presenter = ___VARIABLE_sceneName___Presenter()
33 | presenter.output = viewController
34 |
35 | let interactor = ___VARIABLE_sceneName___Interactor()
36 | interactor.output = presenter
37 |
38 | let router = ___VARIABLE_sceneName___Router(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___InteractorInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___InteractorOutput {
16 |
17 | }
18 |
19 | protocol ___VARIABLE_sceneName___DataSource {
20 |
21 | }
22 |
23 | protocol ___VARIABLE_sceneName___DataDestination {
24 |
25 | }
26 |
27 | class ___VARIABLE_sceneName___Interactor: ___VARIABLE_sceneName___InteractorInput, ___VARIABLE_sceneName___DataSource, ___VARIABLE_sceneName___DataDestination {
28 |
29 | var output: ___VARIABLE_sceneName___InteractorOutput?
30 |
31 | // MARK: Business logic
32 |
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 | //
11 | // Type "usecase" for some magic!
12 |
13 | struct ___VARIABLE_sceneName___Scene {
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_sceneName___PresenterInput {
12 |
13 | }
14 |
15 | protocol ___VARIABLE_sceneName___PresenterOutput: class {
16 |
17 | }
18 |
19 | class ___VARIABLE_sceneName___Presenter: ___VARIABLE_sceneName___PresenterInput {
20 |
21 | weak var output: ___VARIABLE_sceneName___PresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___RouterInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___RouterDataSource: class {
18 |
19 | }
20 |
21 | protocol ___VARIABLE_sceneName___RouterDataDestination: class {
22 |
23 | }
24 |
25 | class ___VARIABLE_sceneName___Router: ___VARIABLE_sceneName___RouterInput {
26 |
27 | weak var viewController: ___VARIABLE_sceneName___ViewController!
28 | weak private var dataSource: ___VARIABLE_sceneName___RouterDataSource!
29 | weak var dataDestination: ___VARIABLE_sceneName___RouterDataDestination!
30 |
31 | init(viewController: ___VARIABLE_sceneName___ViewController, dataSource: ___VARIABLE_sceneName___RouterDataSource, dataDestination: ___VARIABLE_sceneName___RouterDataDestination) {
32 | self.viewController = viewController
33 | self.dataSource = dataSource
34 | self.dataDestination = dataDestination
35 | }
36 |
37 | // MARK: Navigation
38 |
39 | // MARK: Communication
40 |
41 | func passDataToNextScene(for segue: UIStoryboardSegue) {
42 | // NOTE: Teach the router which scenes it can communicate with
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UIViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Store.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Store.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Store.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Store.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Store.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DefaultCompletionName
6 | MyStore
7 | Description
8 | This generates a new Store protocol to access specific entities with CRUD methods.
9 | Kind
10 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
11 | Options
12 |
13 |
14 | Description
15 | The name of the entity to create the store
16 | Identifier
17 | entityName
18 | Name
19 | Entity Name:
20 | NotPersisted
21 |
22 | Required
23 |
24 | Type
25 | text
26 |
27 |
28 | Description
29 | The plural name of the entity to create the store
30 | Identifier
31 | entityPluralName
32 | Name
33 | Plural Name:
34 | Required
35 |
36 | NotPersisted
37 |
38 | Type
39 | text
40 |
41 |
42 | Description
43 | The lowercase name of the entity to create the store
44 | Identifier
45 | entityLowercaseName
46 | Name
47 | Lowercase Name:
48 | Required
49 |
50 | NotPersisted
51 |
52 | Type
53 | text
54 |
55 |
56 | Default
57 | ___VARIABLE_entityName___
58 | Identifier
59 | productName
60 | Type
61 | static
62 |
63 |
64 | Default
65 | ___VARIABLE_entityName:identifier___Store
66 | Description
67 | The store name
68 | Identifier
69 | storeName
70 | Name
71 | Store Name:
72 | Required
73 |
74 | Type
75 | static
76 |
77 |
78 | Platforms
79 |
80 | com.apple.platform.iphoneos
81 |
82 | SortOrder
83 | 2
84 | Summary
85 | This generates a new Store protocol to access specific entities with CRUD methods.
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Store.xctemplate/___FILEBASENAME___Store.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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | protocol ___VARIABLE_entityName___Store {
12 | func get___VARIABLE_entityPluralName___(completion: @escaping ___VARIABLE_entityName___StoreGet___VARIABLE_entityPluralName___CompletionHandler)
13 | func get___VARIABLE_entityName___(withId id: String, completion: @escaping ___VARIABLE_entityName___StoreGet___VARIABLE_entityName___CompletionHandler)
14 | func create___VARIABLE_entityName___(___VARIABLE_entityLowercaseName___ToCreate ___VARIABLE_entityLowercaseName___: ___VARIABLE_entityName___, completion: @escaping ___VARIABLE_entityName___StoreCreate___VARIABLE_entityName___CompletionHandler)
15 | func update___VARIABLE_entityName___(___VARIABLE_entityLowercaseName___ToUpdate ___VARIABLE_entityLowercaseName___: ___VARIABLE_entityName___, completion: @escaping ___VARIABLE_entityName___StoreUpdate___VARIABLE_entityName___CompletionHandler)
16 | func delete___VARIABLE_entityName___(withId id: String, completion: @escaping ___VARIABLE_entityName___StoreDelete___VARIABLE_entityName___CompletionHandler)
17 | }
18 |
19 | typealias ___VARIABLE_entityName___StoreGet___VARIABLE_entityPluralName___CompletionHandler = (___VARIABLE_entityName___StoreResult<[___VARIABLE_entityName___]>) -> Void
20 | typealias ___VARIABLE_entityName___StoreGet___VARIABLE_entityName___CompletionHandler = (___VARIABLE_entityName___StoreResult<___VARIABLE_entityName___>) -> Void
21 | typealias ___VARIABLE_entityName___StoreCreate___VARIABLE_entityName___CompletionHandler = (___VARIABLE_entityName___StoreEmptyResult) -> Void
22 | typealias ___VARIABLE_entityName___StoreUpdate___VARIABLE_entityName___CompletionHandler = (___VARIABLE_entityName___StoreEmptyResult) -> Void
23 | typealias ___VARIABLE_entityName___StoreDelete___VARIABLE_entityName___CompletionHandler = (___VARIABLE_entityName___StoreEmptyResult) -> Void
24 |
25 | enum ___VARIABLE_entityName___StoreResult {
26 | case success(result: U)
27 | case failure(error: ___VARIABLE_entityName___StoreError)
28 | }
29 |
30 | enum ___VARIABLE_entityName___StoreEmptyResult {
31 | case success
32 | case failure(error: ___VARIABLE_entityName___StoreError)
33 | }
34 |
35 | enum ___VARIABLE_entityName___StoreError: Equatable, Error {
36 | case cannotGet(String)
37 | case cannotCreate(String)
38 | case cannotUpdate(String)
39 | case cannotDelete(String)
40 | }
41 |
42 | func ==(lhs: ___VARIABLE_entityName___StoreError, rhs: ___VARIABLE_entityName___StoreError) -> Bool {
43 | switch (lhs, rhs) {
44 | case (.cannotGet(let a), .cannotGet(let b)) where a == b: return true
45 | case (.cannotCreate(let a), .cannotCreate(let b)) where a == b: return true
46 | case (.cannotUpdate(let a), .cannotUpdate(let b)) where a == b: return true
47 | case (.cannotDelete(let a), .cannotDelete(let b)) where a == b: return true
48 | default:
49 | return false
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Unit Tests.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Unit Tests.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Unit Tests.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Unit Tests.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | Platforms
79 |
80 | com.apple.platform.iphoneos
81 |
82 | SortOrder
83 | 1
84 | Summary
85 | This generates unit tests for your scene using Uncle Bob's clean architecture.
86 |
87 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 you can apply
9 | // clean architecture to your iOS and Mac projects, see http://clean-swift.com
10 | //
11 |
12 | @testable import ___PROJECTNAME___
13 | import XCTest
14 |
15 | class ___FILEBASENAMEASIDENTIFIER___InteractorTests: XCTestCase {
16 | // MARK: Subject under test
17 |
18 | var sut: ___FILEBASENAMEASIDENTIFIER___Interactor!
19 |
20 | // MARK: Test lifecycle
21 |
22 | override func setUp() {
23 | super.setUp()
24 | setup___FILEBASENAMEASIDENTIFIER___Interactor()
25 | }
26 |
27 | override func tearDown() {
28 | super.tearDown()
29 | }
30 |
31 | // MARK: Test setup
32 |
33 | func setup___FILEBASENAMEASIDENTIFIER___Interactor() {
34 | sut = ___FILEBASENAMEASIDENTIFIER___Interactor()
35 | }
36 |
37 | // MARK: Test doubles
38 |
39 | // MARK: Tests
40 |
41 | func testSomething() {
42 | // Given
43 |
44 | // When
45 |
46 | // Then
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 you can apply
9 | // clean architecture to your iOS and Mac projects, see http://clean-swift.com
10 | //
11 |
12 | @testable import ___PROJECTNAME___
13 | import XCTest
14 |
15 | class ___FILEBASENAMEASIDENTIFIER___PresenterTests: XCTestCase {
16 | // MARK: Subject under test
17 |
18 | var sut: ___FILEBASENAMEASIDENTIFIER___Presenter!
19 |
20 | // MARK: Test lifecycle
21 |
22 | override func setUp() {
23 | super.setUp()
24 | setup___FILEBASENAMEASIDENTIFIER___Presenter()
25 | }
26 |
27 | override func tearDown() {
28 | super.tearDown()
29 | }
30 |
31 | // MARK: Test setup
32 |
33 | func setup___FILEBASENAMEASIDENTIFIER___Presenter() {
34 | sut = ___FILEBASENAMEASIDENTIFIER___Presenter()
35 | }
36 |
37 | // MARK: Test doubles
38 |
39 | // MARK: Tests
40 |
41 | func testSomething() {
42 | // Given
43 |
44 | // When
45 |
46 | // Then
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 you can apply
9 | // clean architecture to your iOS and Mac projects, see http://clean-swift.com
10 | //
11 |
12 | @testable import ___PROJECTNAME___
13 | import XCTest
14 |
15 | class ___FILEBASENAMEASIDENTIFIER___ViewControllerTests: XCTestCase {
16 | // MARK: Subject under test
17 |
18 | var sut: ___FILEBASENAMEASIDENTIFIER___ViewController!
19 | var window: UIWindow!
20 |
21 | // MARK: Test lifecycle
22 |
23 | override func setUp() {
24 | super.setUp()
25 | window = UIWindow()
26 | setup___FILEBASENAMEASIDENTIFIER___ViewController()
27 | }
28 |
29 | override func tearDown() {
30 | window = nil
31 | super.tearDown()
32 | }
33 |
34 | // MARK: Test setup
35 |
36 | func setup___FILEBASENAMEASIDENTIFIER___ViewController() {
37 | let bundle = Bundle.main
38 | let storyboard = UIStoryboard(name: "Main", bundle: bundle)
39 | sut = storyboard.instantiateViewController(withIdentifier: "___FILEBASENAMEASIDENTIFIER___ViewController") as! ___FILEBASENAMEASIDENTIFIER___ViewController
40 | }
41 |
42 | func loadView() {
43 | window.addSubview(sut.view)
44 | RunLoop.current.run(until: Date())
45 | }
46 |
47 | // MARK: Test doubles
48 |
49 | // MARK: Tests
50 |
51 | func testSomething() {
52 | // Given
53 |
54 | // When
55 |
56 | // Then
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 you can apply
9 | // clean architecture to your iOS and Mac projects, see http://clean-swift.com
10 | //
11 |
12 | @testable import ___PROJECTNAME___
13 | import XCTest
14 |
15 | class ___FILEBASENAMEASIDENTIFIER___WorkerTests: XCTestCase {
16 | // MARK: Subject under test
17 |
18 | var sut: ___FILEBASENAMEASIDENTIFIER___Worker!
19 |
20 | // MARK: Test lifecycle
21 |
22 | override func setUp() {
23 | super.setUp()
24 | setup___FILEBASENAMEASIDENTIFIER___Worker()
25 | }
26 |
27 | override func tearDown() {
28 | super.tearDown()
29 | }
30 |
31 | // MARK: Test setup
32 |
33 | func setup___FILEBASENAMEASIDENTIFIER___Worker() {
34 | sut = ___FILEBASENAMEASIDENTIFIER___Worker()
35 | }
36 |
37 | // MARK: Test doubles
38 |
39 | // MARK: Tests
40 |
41 | func testSomething() {
42 | // Given
43 |
44 | // When
45 |
46 | // Then
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Clean Swift HELM/View Controller.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/View Controller.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/View Controller.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/View Controller.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 8
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 HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UICollectionViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UITableViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | import UIKit
12 |
13 | protocol ___VARIABLE_sceneName___ViewControllerInput {
14 |
15 | }
16 |
17 | protocol ___VARIABLE_sceneName___ViewControllerOutput {
18 |
19 | }
20 |
21 | class ___VARIABLE_sceneName___ViewController: UIViewController, ___VARIABLE_sceneName___ViewControllerInput {
22 |
23 | var output: ___VARIABLE_sceneName___ViewControllerOutput?
24 | var router: ___VARIABLE_sceneName___Router?
25 |
26 | // MARK: Object lifecycle
27 |
28 | override func awakeFromNib() {
29 | super.awakeFromNib()
30 | ___VARIABLE_sceneName___Configurator.sharedInstance.configure(viewController: self)
31 | }
32 |
33 | // MARK: View lifecycle
34 |
35 | override func viewDidLoad() {
36 | super.viewDidLoad()
37 | }
38 |
39 | // MARK: Requests
40 |
41 |
42 | // MARK: Display logic
43 |
44 | }
45 |
46 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
47 | extension ___VARIABLE_sceneName___ViewController: ___VARIABLE_sceneName___PresenterOutput {
48 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
49 | router?.passDataToNextScene(for: segue)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Clean Swift HELM/Worker.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Worker.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Clean Swift HELM/Worker.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelmMobile/clean-swift-templates/8a324044926dd98c37317683b82a2672a4cfccef/Clean Swift HELM/Worker.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Clean Swift HELM/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 | 4
56 | Summary
57 | This generates a new worker to perform your specific business logic.
58 |
59 |
--------------------------------------------------------------------------------
/Clean Swift HELM/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 HELM Xcode Templates
9 | // https://github.com/HelmMobile/clean-swift-templates
10 |
11 | class ___FILEBASENAMEASIDENTIFIER___Worker {
12 | // MARK: Business Logic
13 |
14 | func doSomeWork() {
15 | // NOTE: Do the work
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/Example/Cartfile:
--------------------------------------------------------------------------------
1 |
2 |
3 | github "onevcat/Kingfisher" ~> 3.6
4 | github "Alamofire/Alamofire" ~> 4.4
5 | github "SwiftyJSON/SwiftyJSON" ~> 3.1.4
6 |
--------------------------------------------------------------------------------
/Example/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "Alamofire/Alamofire" "4.4.0"
2 | github "SwiftyJSON/SwiftyJSON" "3.1.4"
3 | github "onevcat/Kingfisher" "3.6.1"
4 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5D3865A41E962BCF00CFEDD1 /* UserDetailViewController+TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D3865A31E962BCF00CFEDD1 /* UserDetailViewController+TableView.swift */; };
11 | 5D3865A71E962DA400CFEDD1 /* UserTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D3865A51E962DA400CFEDD1 /* UserTableViewCell.swift */; };
12 | 5D3865A81E962DA400CFEDD1 /* UserTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5D3865A61E962DA400CFEDD1 /* UserTableViewCell.xib */; };
13 | 5DB2FAC81E94FBE200B0A5CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAC71E94FBE200B0A5CB /* AppDelegate.swift */; };
14 | 5DB2FACD1E94FBE200B0A5CB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5DB2FACB1E94FBE200B0A5CB /* Main.storyboard */; };
15 | 5DB2FACF1E94FBE200B0A5CB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5DB2FACE1E94FBE200B0A5CB /* Assets.xcassets */; };
16 | 5DB2FADA1E94FC3C00B0A5CB /* Cartfile in Resources */ = {isa = PBXBuildFile; fileRef = 5DB2FAD91E94FC3C00B0A5CB /* Cartfile */; };
17 | 5DB2FAE61E95015100B0A5CB /* UserListConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE01E95015100B0A5CB /* UserListConfigurator.swift */; };
18 | 5DB2FAE71E95015100B0A5CB /* UserListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE11E95015100B0A5CB /* UserListInteractor.swift */; };
19 | 5DB2FAE81E95015100B0A5CB /* UserListModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE21E95015100B0A5CB /* UserListModels.swift */; };
20 | 5DB2FAE91E95015100B0A5CB /* UserListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE31E95015100B0A5CB /* UserListPresenter.swift */; };
21 | 5DB2FAEA1E95015100B0A5CB /* UserListRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE41E95015100B0A5CB /* UserListRouter.swift */; };
22 | 5DB2FAEB1E95015100B0A5CB /* UserListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAE51E95015100B0A5CB /* UserListViewController.swift */; };
23 | 5DB2FAED1E95030F00B0A5CB /* UserListViewController+TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAEC1E95030F00B0A5CB /* UserListViewController+TableView.swift */; };
24 | 5DB2FAF51E9506EC00B0A5CB /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DB2FAF21E9506EC00B0A5CB /* Alamofire.framework */; };
25 | 5DB2FAF61E9506EC00B0A5CB /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DB2FAF31E9506EC00B0A5CB /* Kingfisher.framework */; };
26 | 5DB2FAF71E9506EC00B0A5CB /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DB2FAF41E9506EC00B0A5CB /* SwiftyJSON.framework */; };
27 | 5DB2FAFA1E950A5000B0A5CB /* UserListWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAF91E950A5000B0A5CB /* UserListWorker.swift */; };
28 | 5DB2FB011E950BA900B0A5CB /* UserDetailConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAFB1E950BA900B0A5CB /* UserDetailConfigurator.swift */; };
29 | 5DB2FB021E950BA900B0A5CB /* UserDetailInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAFC1E950BA900B0A5CB /* UserDetailInteractor.swift */; };
30 | 5DB2FB031E950BA900B0A5CB /* UserDetailModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAFD1E950BA900B0A5CB /* UserDetailModels.swift */; };
31 | 5DB2FB041E950BA900B0A5CB /* UserDetailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAFE1E950BA900B0A5CB /* UserDetailPresenter.swift */; };
32 | 5DB2FB051E950BA900B0A5CB /* UserDetailRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FAFF1E950BA900B0A5CB /* UserDetailRouter.swift */; };
33 | 5DB2FB061E950BA900B0A5CB /* UserDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB001E950BA900B0A5CB /* UserDetailViewController.swift */; };
34 | 5DB2FB0D1E950C4900B0A5CB /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB0C1E950C4900B0A5CB /* UserStore.swift */; };
35 | 5DB2FB101E950CD600B0A5CB /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB0F1E950CD600B0A5CB /* User.swift */; };
36 | 5DB2FB121E950CEE00B0A5CB /* Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB111E950CEE00B0A5CB /* Name.swift */; };
37 | 5DB2FB151E950D4200B0A5CB /* User+Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB141E950D4200B0A5CB /* User+Network.swift */; };
38 | 5DB2FB171E950D6F00B0A5CB /* Name+Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB161E950D6F00B0A5CB /* Name+Network.swift */; };
39 | 5DB2FB191E950DCF00B0A5CB /* UserNetworkStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB181E950DCF00B0A5CB /* UserNetworkStore.swift */; };
40 | 5DB2FB1B1E950DEA00B0A5CB /* UserNetworkRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB1A1E950DEA00B0A5CB /* UserNetworkRouter.swift */; };
41 | 5DB2FB1E1E950E5900B0A5CB /* SerializableUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DB2FB1D1E950E5900B0A5CB /* SerializableUtils.swift */; };
42 | /* End PBXBuildFile section */
43 |
44 | /* Begin PBXFileReference section */
45 | 5D3865A31E962BCF00CFEDD1 /* UserDetailViewController+TableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDetailViewController+TableView.swift"; sourceTree = ""; };
46 | 5D3865A51E962DA400CFEDD1 /* UserTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserTableViewCell.swift; sourceTree = ""; };
47 | 5D3865A61E962DA400CFEDD1 /* UserTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UserTableViewCell.xib; sourceTree = ""; };
48 | 5DB2FAC41E94FBE200B0A5CB /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 5DB2FAC71E94FBE200B0A5CB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
50 | 5DB2FACC1E94FBE200B0A5CB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
51 | 5DB2FACE1E94FBE200B0A5CB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
52 | 5DB2FAD31E94FBE200B0A5CB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | 5DB2FAD91E94FC3C00B0A5CB /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile; sourceTree = ""; };
54 | 5DB2FAE01E95015100B0A5CB /* UserListConfigurator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListConfigurator.swift; sourceTree = ""; };
55 | 5DB2FAE11E95015100B0A5CB /* UserListInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListInteractor.swift; sourceTree = ""; };
56 | 5DB2FAE21E95015100B0A5CB /* UserListModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListModels.swift; sourceTree = ""; };
57 | 5DB2FAE31E95015100B0A5CB /* UserListPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListPresenter.swift; sourceTree = ""; };
58 | 5DB2FAE41E95015100B0A5CB /* UserListRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListRouter.swift; sourceTree = ""; };
59 | 5DB2FAE51E95015100B0A5CB /* UserListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListViewController.swift; sourceTree = ""; };
60 | 5DB2FAEC1E95030F00B0A5CB /* UserListViewController+TableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserListViewController+TableView.swift"; sourceTree = ""; };
61 | 5DB2FAF21E9506EC00B0A5CB /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; };
62 | 5DB2FAF31E9506EC00B0A5CB /* Kingfisher.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kingfisher.framework; path = Carthage/Build/iOS/Kingfisher.framework; sourceTree = ""; };
63 | 5DB2FAF41E9506EC00B0A5CB /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/iOS/SwiftyJSON.framework; sourceTree = ""; };
64 | 5DB2FAF91E950A5000B0A5CB /* UserListWorker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserListWorker.swift; sourceTree = ""; };
65 | 5DB2FAFB1E950BA900B0A5CB /* UserDetailConfigurator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailConfigurator.swift; sourceTree = ""; };
66 | 5DB2FAFC1E950BA900B0A5CB /* UserDetailInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailInteractor.swift; sourceTree = ""; };
67 | 5DB2FAFD1E950BA900B0A5CB /* UserDetailModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailModels.swift; sourceTree = ""; };
68 | 5DB2FAFE1E950BA900B0A5CB /* UserDetailPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailPresenter.swift; sourceTree = ""; };
69 | 5DB2FAFF1E950BA900B0A5CB /* UserDetailRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailRouter.swift; sourceTree = ""; };
70 | 5DB2FB001E950BA900B0A5CB /* UserDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserDetailViewController.swift; sourceTree = ""; };
71 | 5DB2FB0C1E950C4900B0A5CB /* UserStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserStore.swift; sourceTree = ""; };
72 | 5DB2FB0F1E950CD600B0A5CB /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; };
73 | 5DB2FB111E950CEE00B0A5CB /* Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Name.swift; sourceTree = ""; };
74 | 5DB2FB141E950D4200B0A5CB /* User+Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "User+Network.swift"; sourceTree = ""; };
75 | 5DB2FB161E950D6F00B0A5CB /* Name+Network.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Name+Network.swift"; sourceTree = ""; };
76 | 5DB2FB181E950DCF00B0A5CB /* UserNetworkStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserNetworkStore.swift; sourceTree = ""; };
77 | 5DB2FB1A1E950DEA00B0A5CB /* UserNetworkRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserNetworkRouter.swift; sourceTree = ""; };
78 | 5DB2FB1D1E950E5900B0A5CB /* SerializableUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SerializableUtils.swift; sourceTree = ""; };
79 | /* End PBXFileReference section */
80 |
81 | /* Begin PBXFrameworksBuildPhase section */
82 | 5DB2FAC11E94FBE200B0A5CB /* Frameworks */ = {
83 | isa = PBXFrameworksBuildPhase;
84 | buildActionMask = 2147483647;
85 | files = (
86 | 5DB2FAF51E9506EC00B0A5CB /* Alamofire.framework in Frameworks */,
87 | 5DB2FAF61E9506EC00B0A5CB /* Kingfisher.framework in Frameworks */,
88 | 5DB2FAF71E9506EC00B0A5CB /* SwiftyJSON.framework in Frameworks */,
89 | );
90 | runOnlyForDeploymentPostprocessing = 0;
91 | };
92 | /* End PBXFrameworksBuildPhase section */
93 |
94 | /* Begin PBXGroup section */
95 | 5DB2FABB1E94FBE200B0A5CB = {
96 | isa = PBXGroup;
97 | children = (
98 | 5DB2FAD91E94FC3C00B0A5CB /* Cartfile */,
99 | 5DB2FAC61E94FBE200B0A5CB /* Example */,
100 | 5DB2FAC51E94FBE200B0A5CB /* Products */,
101 | 5DB2FAF11E9506EC00B0A5CB /* Frameworks */,
102 | );
103 | sourceTree = "";
104 | };
105 | 5DB2FAC51E94FBE200B0A5CB /* Products */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 5DB2FAC41E94FBE200B0A5CB /* Example.app */,
109 | );
110 | name = Products;
111 | sourceTree = "";
112 | };
113 | 5DB2FAC61E94FBE200B0A5CB /* Example */ = {
114 | isa = PBXGroup;
115 | children = (
116 | 5DB2FB1C1E950E4D00B0A5CB /* Common */,
117 | 5DB2FB071E950C1700B0A5CB /* Services */,
118 | 5DB2FB0E1E950CC200B0A5CB /* Models */,
119 | 5DB2FADD1E95010300B0A5CB /* Scenes */,
120 | 5DB2FAC71E94FBE200B0A5CB /* AppDelegate.swift */,
121 | 5DB2FACB1E94FBE200B0A5CB /* Main.storyboard */,
122 | 5DB2FACE1E94FBE200B0A5CB /* Assets.xcassets */,
123 | 5DB2FAD31E94FBE200B0A5CB /* Info.plist */,
124 | );
125 | path = Example;
126 | sourceTree = "";
127 | };
128 | 5DB2FADD1E95010300B0A5CB /* Scenes */ = {
129 | isa = PBXGroup;
130 | children = (
131 | 5DB2FADE1E95010300B0A5CB /* UserDetail */,
132 | 5DB2FADF1E95010300B0A5CB /* UserList */,
133 | );
134 | path = Scenes;
135 | sourceTree = "";
136 | };
137 | 5DB2FADE1E95010300B0A5CB /* UserDetail */ = {
138 | isa = PBXGroup;
139 | children = (
140 | 5DB2FAFB1E950BA900B0A5CB /* UserDetailConfigurator.swift */,
141 | 5DB2FAFC1E950BA900B0A5CB /* UserDetailInteractor.swift */,
142 | 5DB2FAFD1E950BA900B0A5CB /* UserDetailModels.swift */,
143 | 5DB2FAFE1E950BA900B0A5CB /* UserDetailPresenter.swift */,
144 | 5DB2FAFF1E950BA900B0A5CB /* UserDetailRouter.swift */,
145 | 5DB2FB001E950BA900B0A5CB /* UserDetailViewController.swift */,
146 | 5D3865A31E962BCF00CFEDD1 /* UserDetailViewController+TableView.swift */,
147 | );
148 | path = UserDetail;
149 | sourceTree = "";
150 | };
151 | 5DB2FADF1E95010300B0A5CB /* UserList */ = {
152 | isa = PBXGroup;
153 | children = (
154 | 5DB2FAEE1E9505C400B0A5CB /* UI */,
155 | 5DB2FAE01E95015100B0A5CB /* UserListConfigurator.swift */,
156 | 5DB2FAE11E95015100B0A5CB /* UserListInteractor.swift */,
157 | 5DB2FAE21E95015100B0A5CB /* UserListModels.swift */,
158 | 5DB2FAE31E95015100B0A5CB /* UserListPresenter.swift */,
159 | 5DB2FAE41E95015100B0A5CB /* UserListRouter.swift */,
160 | 5DB2FAE51E95015100B0A5CB /* UserListViewController.swift */,
161 | 5DB2FAEC1E95030F00B0A5CB /* UserListViewController+TableView.swift */,
162 | 5DB2FAF91E950A5000B0A5CB /* UserListWorker.swift */,
163 | );
164 | path = UserList;
165 | sourceTree = "";
166 | };
167 | 5DB2FAEE1E9505C400B0A5CB /* UI */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 5D3865A51E962DA400CFEDD1 /* UserTableViewCell.swift */,
171 | 5D3865A61E962DA400CFEDD1 /* UserTableViewCell.xib */,
172 | );
173 | path = UI;
174 | sourceTree = "";
175 | };
176 | 5DB2FAF11E9506EC00B0A5CB /* Frameworks */ = {
177 | isa = PBXGroup;
178 | children = (
179 | 5DB2FAF21E9506EC00B0A5CB /* Alamofire.framework */,
180 | 5DB2FAF31E9506EC00B0A5CB /* Kingfisher.framework */,
181 | 5DB2FAF41E9506EC00B0A5CB /* SwiftyJSON.framework */,
182 | );
183 | name = Frameworks;
184 | sourceTree = "";
185 | };
186 | 5DB2FB071E950C1700B0A5CB /* Services */ = {
187 | isa = PBXGroup;
188 | children = (
189 | 5DB2FB081E950C1700B0A5CB /* Stores */,
190 | 5DB2FB131E950D2200B0A5CB /* Mappers */,
191 | );
192 | path = Services;
193 | sourceTree = "";
194 | };
195 | 5DB2FB081E950C1700B0A5CB /* Stores */ = {
196 | isa = PBXGroup;
197 | children = (
198 | 5DB2FB091E950C1700B0A5CB /* Definitions */,
199 | 5DB2FB0A1E950C1700B0A5CB /* Network */,
200 | );
201 | path = Stores;
202 | sourceTree = "";
203 | };
204 | 5DB2FB091E950C1700B0A5CB /* Definitions */ = {
205 | isa = PBXGroup;
206 | children = (
207 | 5DB2FB0C1E950C4900B0A5CB /* UserStore.swift */,
208 | );
209 | path = Definitions;
210 | sourceTree = "";
211 | };
212 | 5DB2FB0A1E950C1700B0A5CB /* Network */ = {
213 | isa = PBXGroup;
214 | children = (
215 | 5DB2FB0B1E950C1700B0A5CB /* Router */,
216 | 5DB2FB181E950DCF00B0A5CB /* UserNetworkStore.swift */,
217 | );
218 | path = Network;
219 | sourceTree = "";
220 | };
221 | 5DB2FB0B1E950C1700B0A5CB /* Router */ = {
222 | isa = PBXGroup;
223 | children = (
224 | 5DB2FB1A1E950DEA00B0A5CB /* UserNetworkRouter.swift */,
225 | );
226 | path = Router;
227 | sourceTree = "";
228 | };
229 | 5DB2FB0E1E950CC200B0A5CB /* Models */ = {
230 | isa = PBXGroup;
231 | children = (
232 | 5DB2FB0F1E950CD600B0A5CB /* User.swift */,
233 | 5DB2FB111E950CEE00B0A5CB /* Name.swift */,
234 | );
235 | path = Models;
236 | sourceTree = "";
237 | };
238 | 5DB2FB131E950D2200B0A5CB /* Mappers */ = {
239 | isa = PBXGroup;
240 | children = (
241 | 5DB2FB141E950D4200B0A5CB /* User+Network.swift */,
242 | 5DB2FB161E950D6F00B0A5CB /* Name+Network.swift */,
243 | );
244 | path = Mappers;
245 | sourceTree = "";
246 | };
247 | 5DB2FB1C1E950E4D00B0A5CB /* Common */ = {
248 | isa = PBXGroup;
249 | children = (
250 | 5DB2FB1D1E950E5900B0A5CB /* SerializableUtils.swift */,
251 | );
252 | path = Common;
253 | sourceTree = "";
254 | };
255 | /* End PBXGroup section */
256 |
257 | /* Begin PBXNativeTarget section */
258 | 5DB2FAC31E94FBE200B0A5CB /* Example */ = {
259 | isa = PBXNativeTarget;
260 | buildConfigurationList = 5DB2FAD61E94FBE200B0A5CB /* Build configuration list for PBXNativeTarget "Example" */;
261 | buildPhases = (
262 | 5DB2FAC01E94FBE200B0A5CB /* Sources */,
263 | 5DB2FAC11E94FBE200B0A5CB /* Frameworks */,
264 | 5DB2FAC21E94FBE200B0A5CB /* Resources */,
265 | 5DB2FAF81E9506FB00B0A5CB /* Carthage dSYMs work around */,
266 | );
267 | buildRules = (
268 | );
269 | dependencies = (
270 | );
271 | name = Example;
272 | productName = Example;
273 | productReference = 5DB2FAC41E94FBE200B0A5CB /* Example.app */;
274 | productType = "com.apple.product-type.application";
275 | };
276 | /* End PBXNativeTarget section */
277 |
278 | /* Begin PBXProject section */
279 | 5DB2FABC1E94FBE200B0A5CB /* Project object */ = {
280 | isa = PBXProject;
281 | attributes = {
282 | LastSwiftUpdateCheck = 0830;
283 | LastUpgradeCheck = 0830;
284 | ORGANIZATIONNAME = "HELM S.C.P.";
285 | TargetAttributes = {
286 | 5DB2FAC31E94FBE200B0A5CB = {
287 | CreatedOnToolsVersion = 8.3;
288 | ProvisioningStyle = Automatic;
289 | };
290 | };
291 | };
292 | buildConfigurationList = 5DB2FABF1E94FBE200B0A5CB /* Build configuration list for PBXProject "Example" */;
293 | compatibilityVersion = "Xcode 3.2";
294 | developmentRegion = English;
295 | hasScannedForEncodings = 0;
296 | knownRegions = (
297 | en,
298 | Base,
299 | );
300 | mainGroup = 5DB2FABB1E94FBE200B0A5CB;
301 | productRefGroup = 5DB2FAC51E94FBE200B0A5CB /* Products */;
302 | projectDirPath = "";
303 | projectRoot = "";
304 | targets = (
305 | 5DB2FAC31E94FBE200B0A5CB /* Example */,
306 | );
307 | };
308 | /* End PBXProject section */
309 |
310 | /* Begin PBXResourcesBuildPhase section */
311 | 5DB2FAC21E94FBE200B0A5CB /* Resources */ = {
312 | isa = PBXResourcesBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | 5D3865A81E962DA400CFEDD1 /* UserTableViewCell.xib in Resources */,
316 | 5DB2FACF1E94FBE200B0A5CB /* Assets.xcassets in Resources */,
317 | 5DB2FADA1E94FC3C00B0A5CB /* Cartfile in Resources */,
318 | 5DB2FACD1E94FBE200B0A5CB /* Main.storyboard in Resources */,
319 | );
320 | runOnlyForDeploymentPostprocessing = 0;
321 | };
322 | /* End PBXResourcesBuildPhase section */
323 |
324 | /* Begin PBXShellScriptBuildPhase section */
325 | 5DB2FAF81E9506FB00B0A5CB /* Carthage dSYMs work around */ = {
326 | isa = PBXShellScriptBuildPhase;
327 | buildActionMask = 2147483647;
328 | files = (
329 | );
330 | inputPaths = (
331 | "$(SRCROOT)/Carthage/Build/iOS/Kingfisher.framework",
332 | "$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework",
333 | "$(SRCROOT)/Carthage/Build/iOS/SwiftyJSON.framework",
334 | );
335 | name = "Carthage dSYMs work around";
336 | outputPaths = (
337 | );
338 | runOnlyForDeploymentPostprocessing = 0;
339 | shellPath = /bin/sh;
340 | shellScript = "/usr/local/bin/carthage copy-frameworks\n";
341 | };
342 | /* End PBXShellScriptBuildPhase section */
343 |
344 | /* Begin PBXSourcesBuildPhase section */
345 | 5DB2FAC01E94FBE200B0A5CB /* Sources */ = {
346 | isa = PBXSourcesBuildPhase;
347 | buildActionMask = 2147483647;
348 | files = (
349 | 5D3865A41E962BCF00CFEDD1 /* UserDetailViewController+TableView.swift in Sources */,
350 | 5D3865A71E962DA400CFEDD1 /* UserTableViewCell.swift in Sources */,
351 | 5DB2FB061E950BA900B0A5CB /* UserDetailViewController.swift in Sources */,
352 | 5DB2FB041E950BA900B0A5CB /* UserDetailPresenter.swift in Sources */,
353 | 5DB2FB011E950BA900B0A5CB /* UserDetailConfigurator.swift in Sources */,
354 | 5DB2FB031E950BA900B0A5CB /* UserDetailModels.swift in Sources */,
355 | 5DB2FB1B1E950DEA00B0A5CB /* UserNetworkRouter.swift in Sources */,
356 | 5DB2FB051E950BA900B0A5CB /* UserDetailRouter.swift in Sources */,
357 | 5DB2FB0D1E950C4900B0A5CB /* UserStore.swift in Sources */,
358 | 5DB2FAE61E95015100B0A5CB /* UserListConfigurator.swift in Sources */,
359 | 5DB2FAEB1E95015100B0A5CB /* UserListViewController.swift in Sources */,
360 | 5DB2FAED1E95030F00B0A5CB /* UserListViewController+TableView.swift in Sources */,
361 | 5DB2FAE91E95015100B0A5CB /* UserListPresenter.swift in Sources */,
362 | 5DB2FB171E950D6F00B0A5CB /* Name+Network.swift in Sources */,
363 | 5DB2FB1E1E950E5900B0A5CB /* SerializableUtils.swift in Sources */,
364 | 5DB2FAE71E95015100B0A5CB /* UserListInteractor.swift in Sources */,
365 | 5DB2FAEA1E95015100B0A5CB /* UserListRouter.swift in Sources */,
366 | 5DB2FAFA1E950A5000B0A5CB /* UserListWorker.swift in Sources */,
367 | 5DB2FB121E950CEE00B0A5CB /* Name.swift in Sources */,
368 | 5DB2FAE81E95015100B0A5CB /* UserListModels.swift in Sources */,
369 | 5DB2FB191E950DCF00B0A5CB /* UserNetworkStore.swift in Sources */,
370 | 5DB2FAC81E94FBE200B0A5CB /* AppDelegate.swift in Sources */,
371 | 5DB2FB021E950BA900B0A5CB /* UserDetailInteractor.swift in Sources */,
372 | 5DB2FB101E950CD600B0A5CB /* User.swift in Sources */,
373 | 5DB2FB151E950D4200B0A5CB /* User+Network.swift in Sources */,
374 | );
375 | runOnlyForDeploymentPostprocessing = 0;
376 | };
377 | /* End PBXSourcesBuildPhase section */
378 |
379 | /* Begin PBXVariantGroup section */
380 | 5DB2FACB1E94FBE200B0A5CB /* Main.storyboard */ = {
381 | isa = PBXVariantGroup;
382 | children = (
383 | 5DB2FACC1E94FBE200B0A5CB /* Base */,
384 | );
385 | name = Main.storyboard;
386 | sourceTree = "";
387 | };
388 | /* End PBXVariantGroup section */
389 |
390 | /* Begin XCBuildConfiguration section */
391 | 5DB2FAD41E94FBE200B0A5CB /* Debug */ = {
392 | isa = XCBuildConfiguration;
393 | buildSettings = {
394 | ALWAYS_SEARCH_USER_PATHS = NO;
395 | CLANG_ANALYZER_NONNULL = YES;
396 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
398 | CLANG_CXX_LIBRARY = "libc++";
399 | CLANG_ENABLE_MODULES = YES;
400 | CLANG_ENABLE_OBJC_ARC = YES;
401 | CLANG_WARN_BOOL_CONVERSION = YES;
402 | CLANG_WARN_CONSTANT_CONVERSION = YES;
403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
404 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
405 | CLANG_WARN_EMPTY_BODY = YES;
406 | CLANG_WARN_ENUM_CONVERSION = YES;
407 | CLANG_WARN_INFINITE_RECURSION = YES;
408 | CLANG_WARN_INT_CONVERSION = YES;
409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
410 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
411 | CLANG_WARN_UNREACHABLE_CODE = YES;
412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
414 | COPY_PHASE_STRIP = NO;
415 | DEBUG_INFORMATION_FORMAT = dwarf;
416 | ENABLE_STRICT_OBJC_MSGSEND = YES;
417 | ENABLE_TESTABILITY = YES;
418 | GCC_C_LANGUAGE_STANDARD = gnu99;
419 | GCC_DYNAMIC_NO_PIC = NO;
420 | GCC_NO_COMMON_BLOCKS = YES;
421 | GCC_OPTIMIZATION_LEVEL = 0;
422 | GCC_PREPROCESSOR_DEFINITIONS = (
423 | "DEBUG=1",
424 | "$(inherited)",
425 | );
426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
428 | GCC_WARN_UNDECLARED_SELECTOR = YES;
429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
430 | GCC_WARN_UNUSED_FUNCTION = YES;
431 | GCC_WARN_UNUSED_VARIABLE = YES;
432 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
433 | MTL_ENABLE_DEBUG_INFO = YES;
434 | ONLY_ACTIVE_ARCH = YES;
435 | SDKROOT = iphoneos;
436 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
437 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
438 | TARGETED_DEVICE_FAMILY = "1,2";
439 | };
440 | name = Debug;
441 | };
442 | 5DB2FAD51E94FBE200B0A5CB /* Release */ = {
443 | isa = XCBuildConfiguration;
444 | buildSettings = {
445 | ALWAYS_SEARCH_USER_PATHS = NO;
446 | CLANG_ANALYZER_NONNULL = YES;
447 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
449 | CLANG_CXX_LIBRARY = "libc++";
450 | CLANG_ENABLE_MODULES = YES;
451 | CLANG_ENABLE_OBJC_ARC = YES;
452 | CLANG_WARN_BOOL_CONVERSION = YES;
453 | CLANG_WARN_CONSTANT_CONVERSION = YES;
454 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
455 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
456 | CLANG_WARN_EMPTY_BODY = YES;
457 | CLANG_WARN_ENUM_CONVERSION = YES;
458 | CLANG_WARN_INFINITE_RECURSION = YES;
459 | CLANG_WARN_INT_CONVERSION = YES;
460 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
461 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
462 | CLANG_WARN_UNREACHABLE_CODE = YES;
463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
465 | COPY_PHASE_STRIP = NO;
466 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
467 | ENABLE_NS_ASSERTIONS = NO;
468 | ENABLE_STRICT_OBJC_MSGSEND = YES;
469 | GCC_C_LANGUAGE_STANDARD = gnu99;
470 | GCC_NO_COMMON_BLOCKS = YES;
471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
473 | GCC_WARN_UNDECLARED_SELECTOR = YES;
474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
475 | GCC_WARN_UNUSED_FUNCTION = YES;
476 | GCC_WARN_UNUSED_VARIABLE = YES;
477 | IPHONEOS_DEPLOYMENT_TARGET = 10.3;
478 | MTL_ENABLE_DEBUG_INFO = NO;
479 | SDKROOT = iphoneos;
480 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
481 | TARGETED_DEVICE_FAMILY = "1,2";
482 | VALIDATE_PRODUCT = YES;
483 | };
484 | name = Release;
485 | };
486 | 5DB2FAD71E94FBE200B0A5CB /* Debug */ = {
487 | isa = XCBuildConfiguration;
488 | buildSettings = {
489 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
490 | FRAMEWORK_SEARCH_PATHS = (
491 | "$(inherited)",
492 | "$(PROJECT_DIR)/Carthage/Build/iOS",
493 | );
494 | INFOPLIST_FILE = Example/Info.plist;
495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
496 | PRODUCT_BUNDLE_IDENTIFIER = cat.helm.Example;
497 | PRODUCT_NAME = "$(TARGET_NAME)";
498 | SWIFT_VERSION = 3.0;
499 | };
500 | name = Debug;
501 | };
502 | 5DB2FAD81E94FBE200B0A5CB /* Release */ = {
503 | isa = XCBuildConfiguration;
504 | buildSettings = {
505 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
506 | FRAMEWORK_SEARCH_PATHS = (
507 | "$(inherited)",
508 | "$(PROJECT_DIR)/Carthage/Build/iOS",
509 | );
510 | INFOPLIST_FILE = Example/Info.plist;
511 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
512 | PRODUCT_BUNDLE_IDENTIFIER = cat.helm.Example;
513 | PRODUCT_NAME = "$(TARGET_NAME)";
514 | SWIFT_VERSION = 3.0;
515 | };
516 | name = Release;
517 | };
518 | /* End XCBuildConfiguration section */
519 |
520 | /* Begin XCConfigurationList section */
521 | 5DB2FABF1E94FBE200B0A5CB /* Build configuration list for PBXProject "Example" */ = {
522 | isa = XCConfigurationList;
523 | buildConfigurations = (
524 | 5DB2FAD41E94FBE200B0A5CB /* Debug */,
525 | 5DB2FAD51E94FBE200B0A5CB /* Release */,
526 | );
527 | defaultConfigurationIsVisible = 0;
528 | defaultConfigurationName = Release;
529 | };
530 | 5DB2FAD61E94FBE200B0A5CB /* Build configuration list for PBXNativeTarget "Example" */ = {
531 | isa = XCConfigurationList;
532 | buildConfigurations = (
533 | 5DB2FAD71E94FBE200B0A5CB /* Debug */,
534 | 5DB2FAD81E94FBE200B0A5CB /* Release */,
535 | );
536 | defaultConfigurationIsVisible = 0;
537 | defaultConfigurationName = Release;
538 | };
539 | /* End XCConfigurationList section */
540 | };
541 | rootObject = 5DB2FABC1E94FBE200B0A5CB /* Project object */;
542 | }
543 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/Example/Example/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 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
93 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/Example/Example/Common/SerializableUtils.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SerializableUtils.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Alamofire
11 | import SwiftyJSON
12 |
13 | protocol ResponseObjectSerializable {
14 | init?(fromJSON json:JSON)
15 | }
16 |
17 | protocol ResponseCollectionSerializable {
18 | static func collection(fromJSON json:JSON) -> [Self]?
19 | }
20 |
21 | extension ResponseCollectionSerializable where Self:ResponseObjectSerializable {
22 |
23 | static func collection(fromJSON json:JSON) -> [Self]? {
24 | var items:[Self] = []
25 | guard let itemsJSON = json.array else {
26 | print(json)
27 | return nil
28 | }
29 | for itemJSON in itemsJSON {
30 | if let item = Self(fromJSON: itemJSON) {
31 | items.append(item)
32 | }
33 | }
34 | return items
35 | }
36 | }
37 |
38 | extension DataRequest {
39 |
40 | func responseObject(
41 | queue: DispatchQueue? = nil,
42 | completionHandler: @escaping (DataResponse) -> Void) -> Self
43 | {
44 | let responseSerializer = DataResponseSerializer { request, response, data, error in
45 | guard error == nil else { return .failure(BackendError.network(error: error!)) }
46 |
47 | let jsonResponseSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
48 | let result = jsonResponseSerializer.serializeResponse(request, response, data, nil)
49 |
50 | guard case let .success(jsonObject) = result else {
51 | return .failure(BackendError.jsonSerialization(error: result.error!))
52 | }
53 |
54 | let json = JSON(jsonObject)
55 |
56 | guard let responseObject = T(fromJSON: json) else {
57 | return .failure(BackendError.objectSerialization(reason: "JSON could not be serialized: \(json)"))
58 | }
59 |
60 | return .success(responseObject)
61 | }
62 |
63 | return response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
64 | }
65 |
66 | @discardableResult
67 | func responseCollection(
68 | queue: DispatchQueue? = nil,
69 | completionHandler: @escaping (DataResponse<[T]>) -> Void) -> Self
70 | {
71 | let responseSerializer = DataResponseSerializer<[T]> { request, response, data, error in
72 | guard error == nil else { return .failure(BackendError.network(error: error!)) }
73 |
74 | let jsonSerializer = DataRequest.jsonResponseSerializer(options: .allowFragments)
75 | let result = jsonSerializer.serializeResponse(request, response, data, nil)
76 |
77 | guard case let .success(jsonObject) = result else {
78 | return .failure(BackendError.jsonSerialization(error: result.error!))
79 | }
80 |
81 | let json = JSON(jsonObject)
82 |
83 | guard response != nil else {
84 | let reason = "Response collection could not be serialized due to nil response."
85 | return .failure(BackendError.objectSerialization(reason: reason))
86 | }
87 |
88 | guard let items = T.collection(fromJSON:json) else {
89 | let reason = "Response collection could not be serialized due to nil serialization."
90 | return .failure(BackendError.objectSerialization(reason: reason))
91 |
92 | }
93 |
94 | return .success(items)
95 | }
96 |
97 | return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
98 | }
99 |
100 | }
101 |
102 | enum BackendError: Error {
103 | case network(error: Error) // Capture any underlying Error from the URLSession API
104 | case dataSerialization(error: Error)
105 | case jsonSerialization(error: Error)
106 | case xmlSerialization(error: Error)
107 | case objectSerialization(reason: String)
108 | }
109 |
--------------------------------------------------------------------------------
/Example/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Example/Example/Models/Name.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Name.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Name {
12 |
13 | let firstName: String
14 | let lastName: String
15 | let title: String
16 |
17 | init(firstName: String, lastName: String, title: String) {
18 | self.firstName = firstName
19 | self.lastName = lastName
20 | self.title = title
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Example/Models/User.swift:
--------------------------------------------------------------------------------
1 | //
2 | // User.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct User {
12 |
13 | let name: Name
14 | let gender: String
15 | let email: String
16 | let mobile: String
17 | let imagePath: String
18 | let thumbImagePath: String
19 |
20 | init(name: Name, gender: String, email: String, mobile: String, imagePath: String, thumbImagePath: String) {
21 | self.name = name
22 | self.gender = gender
23 | self.email = email
24 | self.mobile = mobile
25 | self.imagePath = imagePath
26 | self.thumbImagePath = thumbImagePath
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailConfigurator.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension UserDetailInteractor: UserDetailViewControllerOutput, UserDetailRouterDataSource, UserDetailRouterDataDestination {
16 | }
17 |
18 | extension UserDetailPresenter: UserDetailInteractorOutput {
19 | }
20 |
21 | class UserDetailConfigurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = UserDetailConfigurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: UserDetailViewController) {
31 |
32 | let presenter = UserDetailPresenter()
33 | presenter.output = viewController
34 |
35 | let interactor = UserDetailInteractor()
36 | interactor.output = presenter
37 |
38 | let router = UserDetailRouter(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailInteractor.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | protocol UserDetailInteractorInput {
12 | func getUser(request: UserDetailScene.GetUser.Request)
13 | }
14 |
15 | protocol UserDetailInteractorOutput {
16 | func presentUser(response: UserDetailScene.GetUser.Response)
17 | }
18 |
19 | protocol UserDetailDataSource {
20 |
21 | }
22 |
23 | protocol UserDetailDataDestination {
24 | var user: User! { get set }
25 | }
26 |
27 | class UserDetailInteractor: UserDetailInteractorInput, UserDetailDataSource, UserDetailDataDestination {
28 |
29 | var output: UserDetailInteractorOutput?
30 |
31 | var user: User!
32 |
33 | // MARK: Business logic
34 |
35 | func getUser(request: UserDetailScene.GetUser.Request) {
36 |
37 | // NOTE: Pass the result to the Presenter
38 |
39 | let response = UserDetailScene.GetUser.Response(user: user)
40 | output?.presentUser(response: response)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailModels.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 | // Type "usecase" for some magic!
11 |
12 | struct UserDetailScene {
13 |
14 | struct GetUser {
15 |
16 | struct Request {
17 |
18 | }
19 |
20 | struct Response {
21 | var user: User
22 | }
23 |
24 | struct ViewModel {
25 | let imagePath: String
26 | let atributes: [Atribute]
27 |
28 | struct Atribute {
29 | let title: String
30 | let value: String
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailPresenter.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | protocol UserDetailPresenterInput {
12 | func presentUser(response: UserDetailScene.GetUser.Response)
13 | }
14 |
15 | protocol UserDetailPresenterOutput: class {
16 | func displayUser(viewModel: UserDetailScene.GetUser.ViewModel)
17 | }
18 |
19 | class UserDetailPresenter: UserDetailPresenterInput {
20 |
21 | weak var output: UserDetailPresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | func presentUser(response: UserDetailScene.GetUser.Response) {
26 | let user = response.user
27 |
28 | let viewModel = mapUserToViewModel(user: user)
29 |
30 | output?.displayUser(viewModel: viewModel)
31 | }
32 |
33 | func mapUserToViewModel(user: User) -> UserDetailScene.GetUser.ViewModel {
34 |
35 | let userNameData = user.name
36 | let userName = userNameData.title.capitalized + ". " + userNameData.firstName.capitalized + " " + userNameData.lastName.capitalized
37 |
38 | let nameAtribute = UserDetailScene.GetUser.ViewModel.Atribute(title: "Name: ", value: userName)
39 | let emailAtribute = UserDetailScene.GetUser.ViewModel.Atribute(title: "Email: ", value: user.email)
40 | let mobileAtribute = UserDetailScene.GetUser.ViewModel.Atribute(title: "Mobile: ", value: user.mobile)
41 |
42 | let atributes = [nameAtribute, emailAtribute, mobileAtribute]
43 |
44 | return UserDetailScene.GetUser.ViewModel(imagePath: user.imagePath, atributes: atributes)
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailRouter.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | protocol UserDetailRouterInput {
14 |
15 | }
16 |
17 | protocol UserDetailRouterDataSource: class {
18 |
19 | }
20 |
21 | protocol UserDetailRouterDataDestination: class {
22 | var user: User! { get set }
23 | }
24 |
25 | class UserDetailRouter: UserDetailRouterInput {
26 |
27 | weak var viewController: UserDetailViewController!
28 | weak private var dataSource: UserDetailRouterDataSource!
29 | weak var dataDestination: UserDetailRouterDataDestination!
30 |
31 | init(viewController: UserDetailViewController, dataSource: UserDetailRouterDataSource, dataDestination: UserDetailRouterDataDestination) {
32 | self.viewController = viewController
33 | self.dataSource = dataSource
34 | self.dataDestination = dataDestination
35 | }
36 |
37 | // MARK: Navigation
38 |
39 | // MARK: Communication
40 |
41 | func passDataToNextScene(for segue: UIStoryboardSegue) {
42 | // NOTE: Teach the router which scenes it can communicate with
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailViewController+TableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailViewController+TableView.swift
3 | // Example
4 | //
5 | // Created by Joel on 06/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Kingfisher
11 |
12 | extension UserDetailViewController: UITableViewDelegate, UITableViewDataSource {
13 |
14 | func numberOfSections(in tableView: UITableView) -> Int {
15 | return 1
16 | }
17 |
18 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
19 | return atributes.count
20 | }
21 |
22 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
23 | if let atributeCell = tableView.dequeueReusableCell(withIdentifier: "AtributeCell") {
24 | atributeCell.textLabel?.text = atributes[indexPath.row].title
25 | atributeCell.detailTextLabel?.text = atributes[indexPath.row].value
26 |
27 | return atributeCell
28 | }
29 |
30 | return UITableViewCell()
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserDetail/UserDetailViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDetailViewController.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | protocol UserDetailViewControllerInput {
14 | func displayUser(viewModel: UserDetailScene.GetUser.ViewModel)
15 | }
16 |
17 | protocol UserDetailViewControllerOutput {
18 | func getUser(request: UserDetailScene.GetUser.Request)
19 | }
20 |
21 | class UserDetailViewController: UIViewController, UserDetailViewControllerInput {
22 |
23 | var output: UserDetailViewControllerOutput?
24 | var router: UserDetailRouter?
25 |
26 | @IBOutlet weak var userImage: UIImageView!
27 | @IBOutlet weak var userDataTableView: UITableView!
28 |
29 | var atributes: [UserDetailScene.GetUser.ViewModel.Atribute] = []
30 |
31 | // MARK: Object lifecycle
32 |
33 | override func awakeFromNib() {
34 | super.awakeFromNib()
35 | UserDetailConfigurator.sharedInstance.configure(viewController: self)
36 | }
37 |
38 | // MARK: View lifecycle
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 | getUser()
43 | }
44 |
45 | // MARK: Requests
46 |
47 | func getUser() {
48 | let request = UserDetailScene.GetUser.Request()
49 | output?.getUser(request: request)
50 | }
51 |
52 | // MARK: Display logic
53 |
54 | func displayUser(viewModel: UserDetailScene.GetUser.ViewModel) {
55 |
56 | if let url = URL(string: viewModel.imagePath) {
57 | self.userImage.kf.setImage(with: url)
58 | }
59 |
60 | atributes = viewModel.atributes
61 | userDataTableView.reloadData()
62 | }
63 |
64 |
65 | }
66 |
67 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
68 | extension UserDetailViewController: UserDetailPresenterOutput {
69 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
70 | router?.passDataToNextScene(for: segue)
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UI/UserTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserTableViewCell.swift
3 | // Example
4 | //
5 | // Created by Joel on 06/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class UserTableViewCell: UITableViewCell {
12 |
13 | @IBOutlet weak var userImage: UIImageView!
14 | @IBOutlet weak var userName: UILabel!
15 | @IBOutlet weak var userEmail: UILabel!
16 |
17 | override func awakeFromNib() {
18 | super.awakeFromNib()
19 | }
20 |
21 | override func setSelected(_ selected: Bool, animated: Bool) {
22 | super.setSelected(selected, animated: animated)
23 | }
24 |
25 | func set(user: UserListScene.GetUser.ViewModel.User) {
26 | self.userName.text = user.name
27 | self.userEmail.text = user.email
28 |
29 | if let url = URL(string: user.imagePath) {
30 | self.userImage.kf.setImage(with: url)
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UI/UserTableViewCell.xib:
--------------------------------------------------------------------------------
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 |
42 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListConfigurator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListConfigurator.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | // MARK: Connect View, Interactor, and Presenter
14 |
15 | extension UserListInteractor: UserListViewControllerOutput, UserListRouterDataSource, UserListRouterDataDestination {
16 | }
17 |
18 | extension UserListPresenter: UserListInteractorOutput {
19 | }
20 |
21 | class UserListConfigurator {
22 | // MARK: Object lifecycle
23 |
24 | static let sharedInstance = UserListConfigurator()
25 |
26 | private init() {}
27 |
28 | // MARK: Configuration
29 |
30 | func configure(viewController: UserListViewController) {
31 |
32 | let presenter = UserListPresenter()
33 | presenter.output = viewController
34 |
35 | let interactor = UserListInteractor()
36 | interactor.output = presenter
37 |
38 | let router = UserListRouter(viewController: viewController, dataSource: interactor, dataDestination: interactor)
39 |
40 | viewController.output = interactor
41 | viewController.router = router
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListInteractor.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | protocol UserListInteractorInput {
12 | func getUser(request: UserListScene.GetUser.Request)
13 | func selectUser(request: UserListScene.SelectUser.Request)
14 | }
15 |
16 | protocol UserListInteractorOutput {
17 | func presentUser(response: UserListScene.GetUser.Response)
18 | }
19 |
20 | protocol UserListDataSource {
21 | var selectedUser: User! { get }
22 | }
23 |
24 | protocol UserListDataDestination {
25 |
26 | }
27 |
28 | class UserListInteractor: UserListInteractorInput, UserListDataSource, UserListDataDestination {
29 |
30 | var output: UserListInteractorOutput?
31 | var worker: UserListWorker?
32 |
33 | var users: [User] = []
34 | var selectedUser: User!
35 |
36 | // MARK: Business logic
37 |
38 | func getUser(request: UserListScene.GetUser.Request)
39 | {
40 | worker = UserListWorker(store: UserNetworkStore())
41 | worker?.getUser {(result: UserStoreResult) -> Void in
42 |
43 | switch result {
44 | case .success(let user):
45 | self.users.insert(user, at: 0)
46 | let response = UserListScene.GetUser.Response(newUser: user)
47 | self.output?.presentUser(response: response)
48 | case .failure(let error):
49 | print(error)
50 | }
51 | }
52 | }
53 |
54 | func selectUser(request: UserListScene.SelectUser.Request) {
55 | selectedUser = users[request.index]
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListModels.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 | // Type "usecase" for some magic!
11 |
12 | struct UserListScene {
13 |
14 | struct GetUser {
15 |
16 | struct Request {
17 |
18 | }
19 |
20 | struct Response {
21 | var newUser: User
22 | }
23 |
24 | struct ViewModel {
25 | let user: User
26 |
27 | struct User {
28 | let name: String
29 | let email: String
30 | let imagePath: String
31 | }
32 | }
33 | }
34 |
35 | struct SelectUser {
36 |
37 | struct Request {
38 | let index:Int
39 | }
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListPresenter.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | protocol UserListPresenterInput {
12 | func presentUser(response: UserListScene.GetUser.Response)
13 | }
14 |
15 | protocol UserListPresenterOutput: class {
16 | func displayUser(viewModel: UserListScene.GetUser.ViewModel)
17 | }
18 |
19 | class UserListPresenter: UserListPresenterInput {
20 |
21 | weak var output: UserListPresenterOutput?
22 |
23 | // MARK: Presentation logic
24 |
25 | func presentUser(response: UserListScene.GetUser.Response)
26 | {
27 | // NOTE: Format the response from the Interactor and pass the result back to the View Controller
28 |
29 | let user = response.newUser
30 |
31 | let userNameData = user.name
32 | let userName = userNameData.title.capitalized + ". " + userNameData.firstName.capitalized + " " + userNameData.lastName.capitalized
33 |
34 | let userViewModel = UserListScene.GetUser.ViewModel.User(name: userName, email: user.email, imagePath: user.thumbImagePath)
35 |
36 | let viewModel = UserListScene.GetUser.ViewModel(user: userViewModel)
37 |
38 | output?.displayUser(viewModel: viewModel)
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListRouter.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | protocol UserListRouterInput {
14 | func navigateToUserDetailScene()
15 | }
16 |
17 | protocol UserListRouterDataSource: class {
18 | var selectedUser: User! { get }
19 | }
20 |
21 | protocol UserListRouterDataDestination: class {
22 |
23 | }
24 |
25 | class UserListRouter: UserListRouterInput {
26 |
27 | weak var viewController: UserListViewController!
28 | weak private var dataSource: UserListRouterDataSource!
29 | weak var dataDestination: UserListRouterDataDestination!
30 |
31 | struct SegueIdentifiers {
32 | static let userDetail = "UserDetailScene"
33 | }
34 |
35 | init(viewController: UserListViewController, dataSource: UserListRouterDataSource, dataDestination: UserListRouterDataDestination) {
36 | self.viewController = viewController
37 | self.dataSource = dataSource
38 | self.dataDestination = dataDestination
39 | }
40 |
41 | // MARK: Navigation
42 |
43 | func navigateToUserDetailScene()
44 | {
45 | viewController.performSegue(withIdentifier: SegueIdentifiers.userDetail, sender: viewController)
46 | }
47 |
48 | // MARK: Communication
49 |
50 | func passDataToNextScene(for segue: UIStoryboardSegue) {
51 | // NOTE: Teach the router which scenes it can communicate with
52 |
53 | guard let segueIdentifier = segue.identifier else {
54 | return
55 | }
56 |
57 | switch segueIdentifier {
58 | case SegueIdentifiers.userDetail:
59 | passDataToUserDetailScene(for: segue)
60 | default:
61 | return
62 | }
63 | }
64 |
65 | func passDataToUserDetailScene(for segue: UIStoryboardSegue)
66 | {
67 | // NOTE: Teach the router how to pass data to the next scene
68 |
69 | if let userDetailViewController = segue.destination as? UserDetailViewController {
70 | userDetailViewController.router?.dataDestination.user = dataSource.selectedUser
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListViewController+TableView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListViewController+TableView.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UserListViewController: UITableViewDelegate, UITableViewDataSource {
12 |
13 | func configureTableViewOnLoad() {
14 | userListTableView.register(UINib(nibName: "UserTableViewCell", bundle: Bundle.main), forCellReuseIdentifier: cellIdentifiers.userCell)
15 | }
16 |
17 | func numberOfSections(in tableView: UITableView) -> Int {
18 | return 1
19 | }
20 |
21 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
22 | return users.count
23 | }
24 |
25 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
26 | let displayUser = users[indexPath.row]
27 |
28 | if let userCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifiers.userCell) as? UserTableViewCell {
29 | userCell.set(user: displayUser)
30 |
31 | return userCell
32 | }
33 |
34 | return UITableViewCell()
35 | }
36 |
37 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
38 | let request = UserListScene.SelectUser.Request(index: indexPath.row)
39 | output?.selectUser(request: request)
40 | router?.navigateToUserDetailScene()
41 | tableView.deselectRow(at: indexPath, animated: true)
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListViewController.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | import UIKit
12 |
13 | protocol UserListViewControllerInput {
14 | func displayUser(viewModel: UserListScene.GetUser.ViewModel)
15 | }
16 |
17 | protocol UserListViewControllerOutput {
18 | func getUser(request: UserListScene.GetUser.Request)
19 | func selectUser(request: UserListScene.SelectUser.Request)
20 | }
21 |
22 | class UserListViewController: UIViewController, UserListViewControllerInput {
23 |
24 | var output: UserListViewControllerOutput?
25 | var router: UserListRouter?
26 | var users: [UserListScene.GetUser.ViewModel.User] = []
27 |
28 | @IBOutlet weak var userListTableView: UITableView!
29 |
30 | struct cellIdentifiers {
31 | static let userCell = "userCell"
32 | }
33 |
34 | // MARK: Object lifecycle
35 |
36 | override func awakeFromNib() {
37 | super.awakeFromNib()
38 | UserListConfigurator.sharedInstance.configure(viewController: self)
39 | }
40 |
41 | // MARK: View lifecycle
42 |
43 | override func viewDidLoad() {
44 | super.viewDidLoad()
45 | configureTableViewOnLoad()
46 | }
47 |
48 | // MARK: Requests
49 |
50 | func requestGetUser() {
51 | let request = UserListScene.GetUser.Request()
52 | output?.getUser(request: request)
53 | }
54 |
55 | // MARK: Display logic
56 |
57 | func displayUser(viewModel: UserListScene.GetUser.ViewModel) {
58 | let user = viewModel.user
59 | users.insert(user, at: 0)
60 | userListTableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .right)
61 | }
62 |
63 | // MARK: UI events
64 |
65 | @IBAction func addUserButtonClicked(_ sender: UIBarButtonItem) {
66 | requestGetUser()
67 | }
68 |
69 |
70 | }
71 |
72 | //This should be on configurator but for some reason storyboard doesn't detect ViewController's name if placed there
73 | extension UserListViewController: UserListPresenterOutput {
74 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
75 | router?.passDataToNextScene(for: segue)
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Example/Example/Scenes/UserList/UserListWorker.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserListWorker.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | class UserListWorker {
12 | // MARK: Business Logic
13 |
14 | let store: UserStore
15 |
16 | init(store: UserStore) {
17 | self.store = store
18 | }
19 |
20 | func getUser(completionHandler: @escaping (UserStoreResult) -> Void){
21 | store.getUser(completion: completionHandler)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Example/Example/Services/Mappers/Name+Network.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Name+API.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SwiftyJSON
11 |
12 | extension Name: ResponseObjectSerializable {
13 |
14 | init?(fromJSON json: JSON) {
15 |
16 | guard let firstName = json["first"].string
17 | ,let lastName = json["last"].string
18 | ,let title = json["title"].string else {
19 | return nil
20 | }
21 |
22 | self.firstName = firstName
23 | self.lastName = lastName
24 | self.title = title
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Example/Example/Services/Mappers/User+Network.swift:
--------------------------------------------------------------------------------
1 | //
2 | // User+API.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SwiftyJSON
11 |
12 | extension User: ResponseObjectSerializable {
13 |
14 | init?(fromJSON json: JSON) {
15 |
16 | let userData = json["results"][0]
17 | let nameData = userData["name"]
18 |
19 | guard let mobile = userData["cell"].string
20 | ,let email = userData["email"].string
21 | ,let gender = userData["gender"].string
22 | ,let imagePath = userData["picture"]["large"].string
23 | ,let thumbImagePath = userData["picture"]["thumbnail"].string
24 | ,let name = Name(fromJSON: nameData) else {
25 |
26 | return nil
27 | }
28 |
29 | self.mobile = mobile
30 | self.email = email
31 | self.gender = gender
32 | self.imagePath = imagePath
33 | self.thumbImagePath = thumbImagePath
34 | self.name = name
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Example/Example/Services/Stores/Definitions/UserStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserStore.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright (c) 2017 HELM S.C.P. All rights reserved.
7 | //
8 | // This file was generated by the Clean Swift HELM Xcode Templates
9 | //
10 |
11 | protocol UserStore {
12 | func getUser(completion: @escaping UserStoreGetUserCompletionHandler)
13 | }
14 |
15 | typealias UserStoreGetUserCompletionHandler = (UserStoreResult) -> Void
16 |
17 | enum UserStoreResult {
18 | case success(result: U)
19 | case failure(error: UserStoreError)
20 | }
21 |
22 | enum UserStoreEmptyResult {
23 | case success
24 | case failure(error: UserStoreError)
25 | }
26 |
27 | enum UserStoreError: Equatable, Error {
28 | case cannotGet(String)
29 | }
30 |
31 | func ==(lhs: UserStoreError, rhs: UserStoreError) -> Bool {
32 | switch (lhs, rhs) {
33 | case (.cannotGet(let a), .cannotGet(let b)) where a == b: return true
34 | default:
35 | return false
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Example/Example/Services/Stores/Network/Router/UserNetworkRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserNetworkRouter.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Alamofire
11 |
12 | enum UserNetworkRouter:URLRequestConvertible {
13 |
14 | static let baseURL = "https://randomuser.me/api/"
15 |
16 | case getUser()
17 |
18 | func asURLRequest() throws -> URLRequest {
19 | var request: URLRequest!
20 |
21 | switch self {
22 | case .getUser():
23 | let url = URL(string: UserNetworkRouter.baseURL)!
24 | request = URLRequest(url: url)
25 | request.httpMethod = "GET"
26 | }
27 |
28 | return try Alamofire.URLEncoding().encode(request, with: nil)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Example/Example/Services/Stores/Network/UserNetworkStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserNetworkStore.swift
3 | // Example
4 | //
5 | // Created by Joel on 05/04/2017.
6 | // Copyright © 2017 HELM S.C.P. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import Alamofire
11 |
12 | class UserNetworkStore: UserStore {
13 |
14 | func getUser(completion: @escaping UserStoreGetUserCompletionHandler) {
15 | _ = Alamofire.request(UserNetworkRouter.getUser())
16 | .validate()
17 | .responseObject { (response: DataResponse) in
18 | switch response.result {
19 | case .success(let user):
20 | completion(.success(result: user))
21 | case .failure(let error):
22 | completion(.failure(error: UserStoreError.cannotGet("Cannot get user \(error)")))
23 | }
24 | }
25 |
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Example/cartupdate.sh:
--------------------------------------------------------------------------------
1 | carthage update --platform iOS --no-use-binaries
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Original work Copyright (c) 2015 Raymond Law (http://clean-swift.com)
4 | Modified work Copyright (c) 2016 Miguel Berrocal HELM S.C.P (www.helm.cat)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | XCODE_USER_TEMPLATES_DIR=~/Library/Developer/Xcode/Templates/File\ Templates
2 | XCODE_USER_SNIPPETS_DIR=~/Library/Developer/Xcode/UserData/CodeSnippets
3 | SNIPPETS_PREFIX=clean-swift
4 |
5 | TEMPLATES_DIR=Clean\ Swift\ HELM
6 | SNIPPETS_DIR=Snippets
7 |
8 | install:install_templates install_snippets
9 | @echo "Install Done"
10 |
11 | install_templates:
12 | @mkdir -p $(XCODE_USER_TEMPLATES_DIR)
13 | @rm -fR $(XCODE_USER_TEMPLATES_DIR)/$(TEMPLATES_DIR)
14 | @cp -R $(TEMPLATES_DIR) $(XCODE_USER_TEMPLATES_DIR)
15 |
16 | install_snippets:
17 | @mkdir -p $(XCODE_USER_SNIPPETS_DIR)
18 | @rm -fR $(XCODE_USER_SNIPPETS_DIR)/$(SNIPPETS_PREFIX)*
19 | @cp $(SNIPPETS_DIR)/* $(XCODE_USER_SNIPPETS_DIR)
20 | @echo "Restart Xcode to see changes!"
21 |
22 | uninstall_templates:
23 | @rm -fR $(XCODE_USER_TEMPLATES_DIR)/$(TEMPLATES_DIR)
24 |
25 | uninstall_snippets:
26 | @rm -fR $(XCODE_USER_SNIPPETS_DIR)/$(SNIPPETS_PREFIX)*
27 |
28 | uninstall: uninstall_templates uninstall_snippets
29 | @echo "Uninstall Done"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Clean-swift templates
2 |
3 | This is a modification of Clean Swift Templates (http://clean-swift.com) made by HELM (www.helm.cat)
4 |
5 | To learn more about Clean Swift and the VIP cycle, read:
6 |
7 | http://clean-swift.com/clean-swift-ios-architecture
8 |
9 | # Changelog
10 |
11 | This modification aims to create work-ready templates and snippets to achieve the maximum efficiency for people who are already familiar with them. Furthermore we added some extra features in order to attempt to solve some issues.
12 |
13 | Here is a list of what is modified:
14 | * Indent is changed to a standarized 4-spaces indent
15 | * Braces follow the OTBS (https://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)
16 | * Deleted all example functions (doSomething, presentSomething, etc.) aswell as example models
17 | * Deleted worker auto-creation from Scene template
18 |
19 | Added features:
20 | * Awesome snippet to create usecases
21 | * New data-passing method
22 | * Added Store Template
23 |
24 | ## Snippet
25 | 
26 |
27 | ## New data-passing method
28 | Previously to pass data we need to do something like this in the source Router:
29 | ```swift
30 | let user = sourceViewController.output.selectedUser
31 | destinationViewController.output.user = user
32 | ```
33 | We think this is wrong because:
34 |
35 | 1. We are not trying to output anything from the ViewController.
36 | 2. We are assuming the output === Interactor and the architecture loses sense (no component should know about what kind of object its output/input is).
37 | 3. We dont want the ViewController to know anything about Business model.
38 | 4. We want the Interactor to handle this data but we don't want the ViewController to know anything about it.
39 |
40 | So we added 2 new protocols on the router
41 |
42 | ```swift
43 | protocol RouterDataSource: class {
44 |
45 | }
46 | protocol RouterDataDestination: class {
47 |
48 | }
49 | ```
50 | - The RouterDataSource protocol is used to determine what business data has to be passed somewhere.
51 | - The RouterDataDestination protocol is used to determine what data has to be received and handled by this scene.
52 |
53 | So following the example before we would add this in the source Router:
54 | ```swift
55 | protocol UserListRouterDataSource: class {
56 | var selectedUser: User! { get }
57 | }
58 |
59 | protocol UserListRouterDataDestination: class {
60 |
61 | }
62 | ```
63 |
64 | And this in the destination:
65 | ```swift
66 | protocol UserDetailRouterDataSource: class {
67 |
68 | }
69 |
70 | protocol UserDetailRouterDataDestination: class {
71 | var user: User! { get set }
72 | }
73 | ```
74 |
75 | As we added a dataSource object and a dataDestination object in the Router, we can now do this:
76 |
77 | ```
78 | let user = dataSource.selectedUser
79 | userDetailViewController.router.dataDestination.user = user
80 | ```
81 |
82 | As previously mentioned we believe this handling should be done by the Interactor aswell but without the ViewController knowing it so we added the protocols there and changed the Configurator.swift in order to connect both protocols.
83 |
84 | So the source Interactor would look like this:
85 | ```swift
86 | protocol UserListDataSource {
87 | var selectedUser: User! { get }
88 | }
89 |
90 | protocol UserListDataDestination {
91 |
92 | }
93 |
94 | class UserListInteractor: UserListInteractorInput, UserListDataSource, UserListDataDestination {
95 | ```
96 |
97 | And as you would assume, the destination Interactor looks like this:
98 |
99 | ```swift
100 | protocol UserDetailDataSource {
101 |
102 | }
103 |
104 | protocol UserDetailDataDestination {
105 | var user: User! { get set }
106 | }
107 |
108 | class UserDetailInteractor: UserDetailInteractorInput, UserDetailDataSource, UserDetailDataDestination {
109 | ```
110 |
111 | You can see a working example in the Example folder.
112 |
113 | # Installation
114 |
115 | To install the Clean Swift Xcode HELM templates and snippets, run:
116 | ```
117 | ./configure
118 | make install
119 | ```
120 | To uninstall the Clean Swift Xcode templates and snippets, run:
121 | ```
122 | make uninstall
123 | ```
124 |
125 | To try the Example project you need carthage:
126 | ```
127 | brew update
128 | brew install carthage
129 | ```
130 |
131 | Then run
132 | ```
133 | ./cartupdate.sh
134 | ```
135 |
136 | In the project folder (/Example)
137 |
--------------------------------------------------------------------------------
/Snippets/clean-swift-use-case.codesnippet:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDECodeSnippetCompletionPrefix
6 | clean-swift usecase
7 | IDECodeSnippetCompletionScopes
8 |
9 | ClassImplementation
10 |
11 | IDECodeSnippetContents
12 | struct <#Use Case#> {
13 |
14 | struct Request {
15 |
16 | }
17 |
18 | struct Response {
19 |
20 | }
21 |
22 | struct ViewModel {
23 |
24 | }
25 | }
26 | IDECodeSnippetIdentifier
27 | EE0E1F91-B40D-4ADD-8B2D-C44D2B7DC9C3
28 | IDECodeSnippetLanguage
29 | Xcode.SourceCodeLanguage.Swift
30 | IDECodeSnippetSummary
31 | Creates necessary models for a use case
32 | IDECodeSnippetTitle
33 | Clean Swift - Use Case Models
34 | IDECodeSnippetUserSnippet
35 |
36 | IDECodeSnippetVersion
37 | 2
38 | Author
39 | Miguel Berrocal (miguel@helm.cat)
40 |
41 |
42 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.1.2
--------------------------------------------------------------------------------
/configure:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #JesusCamacho
3 |
4 | view="UIViewController"
5 | table="UITableViewController"
6 | collection="UICollectionViewController"
7 |
8 | #Eliminamos directorios de Clean Swift HELM/Scene.xctemplate
9 | rm -rf Clean\ Swift\ HELM/Scene.xctemplate/$view
10 | rm -rf Clean\ Swift\ HELM/Scene.xctemplate/$table
11 | rm -rf Clean\ Swift\ HELM/Scene.xctemplate/$collection
12 |
13 | # Copiamos los tres directorios de View Controller.xctemplate a Scene.xctemplate
14 | cp -rf Clean\ Swift\ HELM/View\ Controller.xctemplate/$view Clean\ Swift\ HELM/Scene.xctemplate
15 | cp -rf Clean\ Swift\ HELM/View\ Controller.xctemplate/$table Clean\ Swift\ HELM/Scene.xctemplate
16 | cp -rf Clean\ Swift\ HELM/View\ Controller.xctemplate/$collection Clean\ Swift\ HELM/Scene.xctemplate
17 |
18 | # Copiamos los .swift dentro de $view, $table, $collection
19 | ## Configurator.xctemplate
20 | config="Configurator.xctemplate"
21 | configFile="___FILEBASENAME___Configurator.swift"
22 | cp Clean\ Swift\ HELM/$config/$configFile Clean\ Swift\ HELM/Scene.xctemplate/$view
23 | cp Clean\ Swift\ HELM/$config/$configFile Clean\ Swift\ HELM/Scene.xctemplate/$table
24 | cp Clean\ Swift\ HELM/$config/$configFile Clean\ Swift\ HELM/Scene.xctemplate/$collection
25 |
26 | ## Interactor.xctemplate
27 | int="Interactor.xctemplate"
28 | intFile="___FILEBASENAME___Interactor.swift"
29 | cp Clean\ Swift\ HELM/$int/$intFile Clean\ Swift\ HELM/Scene.xctemplate/$view
30 | cp Clean\ Swift\ HELM/$int/$intFile Clean\ Swift\ HELM/Scene.xctemplate/$table
31 | cp Clean\ Swift\ HELM/$int/$intFile Clean\ Swift\ HELM/Scene.xctemplate/$collection
32 |
33 | ## Models.xctemplate
34 | model="Models.xctemplate"
35 | modelFile="___FILEBASENAME___Models.swift"
36 | cp Clean\ Swift\ HELM/$model/$modelFile Clean\ Swift\ HELM/Scene.xctemplate/$view
37 | cp Clean\ Swift\ HELM/$model/$modelFile Clean\ Swift\ HELM/Scene.xctemplate/$table
38 | cp Clean\ Swift\ HELM/$model/$modelFile Clean\ Swift\ HELM/Scene.xctemplate/$collection
39 |
40 | ## Presenter.xctemplate
41 | pres="Presenter.xctemplate"
42 | presFile="___FILEBASENAME___Presenter.swift"
43 | cp Clean\ Swift\ HELM/$pres/$presFile Clean\ Swift\ HELM/Scene.xctemplate/$view
44 | cp Clean\ Swift\ HELM/$pres/$presFile Clean\ Swift\ HELM/Scene.xctemplate/$table
45 | cp Clean\ Swift\ HELM/$pres/$presFile Clean\ Swift\ HELM/Scene.xctemplate/$collection
46 |
47 | ## Router.xctemplate
48 | router="Router.xctemplate"
49 | routerFile="___FILEBASENAME___Router.swift"
50 | cp Clean\ Swift\ HELM/$router/$routerFile Clean\ Swift\ HELM/Scene.xctemplate/$view
51 | cp Clean\ Swift\ HELM/$router/$routerFile Clean\ Swift\ HELM/Scene.xctemplate/$table
52 | cp Clean\ Swift\ HELM/$router/$routerFile Clean\ Swift\ HELM/Scene.xctemplate/$collection
53 |
54 |
55 |
--------------------------------------------------------------------------------