├── .swift-version
├── Assets
├── SwiftyVIPER.png
├── SwiftyVIPER.psd
├── Template Name.png
└── Template Choice.png
├── codecov.yml
├── Example
├── SwiftyVIPERExample
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── SwiftyVIPER.imageset
│ │ │ ├── SwiftyVIPER@2x.png
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Modules
│ │ ├── DetailRouter.swift
│ │ ├── RootInteractor.swift
│ │ ├── DetailInteractor.swift
│ │ ├── RootRouter.swift
│ │ ├── RootModule.swift
│ │ ├── DetailModule.swift
│ │ ├── DetailViewController.swift
│ │ ├── RootPresenter.swift
│ │ ├── DetailPresenter.swift
│ │ └── RootViewController.swift
│ ├── AppDelegate.swift
│ ├── Info.plist
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── SwiftyVIPERExample.xcodeproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── project.pbxproj
├── SwiftyVIPERExample.xcworkspace
│ └── contents.xcworkspacedata
├── Podfile
├── Podfile.lock
├── SwiftyVIPERExampleTests
│ ├── Info.plist
│ ├── DetailRouterTests.swift
│ ├── RootRouterTests.swift
│ ├── RootModuleTests.swift
│ ├── DetailInteractorTests.swift
│ ├── RootInteractorTests.swift
│ ├── DetailModuleTests.swift
│ ├── RootViewTests.swift
│ ├── DetailViewTests.swift
│ ├── RootPresenterTests.swift
│ └── DetailPresenterTests.swift
└── .swiftlint.yml
├── Templates
└── VIPER
│ ├── Module.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── ___FILEBASENAME___Router.swift
│ ├── ___FILEBASENAME___Interactor.swift
│ ├── ___FILEBASENAME___Module.swift
│ ├── TemplateInfo.plist
│ ├── ___FILEBASENAME___ViewController.swift
│ └── ___FILEBASENAME___Presenter.swift
│ ├── Module Tests.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── ___FILEBASENAME___RouterTests.swift
│ ├── TemplateInfo.plist
│ ├── ___FILEBASENAME___ModuleTests.swift
│ ├── ___FILEBASENAME___InteractorTests.swift
│ ├── ___FILEBASENAME___ViewTests.swift
│ └── ___FILEBASENAME___PresenterTests.swift
│ └── Module Storyboard.xctemplate
│ ├── TemplateIcon.png
│ ├── TemplateIcon@2x.png
│ ├── ___FILEBASENAME___Router.swift
│ ├── ___FILEBASENAME___Interactor.swift
│ ├── ___FILEBASENAME___ViewController.swift
│ ├── TemplateInfo.plist
│ ├── ___FILEBASENAME___Module.swift
│ └── ___FILEBASENAME___Presenter.swift
├── Build-Phases
└── swiftlint.sh
├── SwiftyVIPER.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ ├── SwiftyVIPERiOS.xcscheme
│ │ └── SwiftyVIPERtvOS.xcscheme
└── project.pbxproj
├── .editorconfig
├── Sources
├── SwiftyVIPER.h
├── Info.plist
├── Extensions.swift
└── Protocols.swift
├── SwiftyVIPER.podspec
├── Tests
├── Info.plist
├── MockModule.swift
├── tvOS.storyboard
├── iOS.storyboard
└── ProtocolTests.swift
├── .travis.yml
├── LICENSE
├── .gitignore
├── .swiftlint.yml
├── CHANGELOG.md
└── README.md
/.swift-version:
--------------------------------------------------------------------------------
1 | 4.0
2 |
--------------------------------------------------------------------------------
/Assets/SwiftyVIPER.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Assets/SwiftyVIPER.png
--------------------------------------------------------------------------------
/Assets/SwiftyVIPER.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Assets/SwiftyVIPER.psd
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | ignore:
3 | - Tests/*
4 | - Example/SwiftyVIPERExampleTests/*
5 |
--------------------------------------------------------------------------------
/Assets/Template Name.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Assets/Template Name.png
--------------------------------------------------------------------------------
/Assets/Template Choice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Assets/Template Choice.png
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module Tests.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module Tests.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/TemplateIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module Storyboard.xctemplate/TemplateIcon.png
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/TemplateIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Templates/VIPER/Module Storyboard.xctemplate/TemplateIcon@2x.png
--------------------------------------------------------------------------------
/Build-Phases/swiftlint.sh:
--------------------------------------------------------------------------------
1 | if which swiftlint >/dev/null; then
2 | swiftlint
3 | else
4 | echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
5 | fi
6 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Assets.xcassets/SwiftyVIPER.imageset/SwiftyVIPER@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codytwinton/SwiftyVIPER/HEAD/Example/SwiftyVIPERExample/Assets.xcassets/SwiftyVIPER.imageset/SwiftyVIPER@2x.png
--------------------------------------------------------------------------------
/SwiftyVIPER.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 |
2 | # Cocoapod
3 | source 'https://github.com/CocoaPods/Specs.git'
4 | use_frameworks!
5 | platform :ios, '8.0'
6 | inhibit_all_warnings!
7 |
8 |
9 | def shared_pods
10 | pod 'SnapKit', '~> 4.0'
11 | pod 'SwiftLint'
12 | pod 'SwiftyVIPER', :path => '../'
13 | end
14 |
15 | target 'SwiftyVIPERExample' do
16 | shared_pods
17 | end
18 |
19 | target 'SwiftyVIPERExampleTests' do
20 | shared_pods
21 | end
22 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Assets.xcassets/SwiftyVIPER.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "SwiftyVIPER@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SnapKit (4.0.0)
3 | - SwiftLint (0.24.2)
4 | - SwiftyVIPER (1.2.3)
5 |
6 | DEPENDENCIES:
7 | - SnapKit (~> 4.0)
8 | - SwiftLint
9 | - SwiftyVIPER (from `../`)
10 |
11 | EXTERNAL SOURCES:
12 | SwiftyVIPER:
13 | :path: ../
14 |
15 | SPEC CHECKSUMS:
16 | SnapKit: a42d492c16e80209130a3379f73596c3454b7694
17 | SwiftLint: 2aa21b96c8d13396a051bc1cb659d2ce1e0075b0
18 | SwiftyVIPER: f0d3130dc59b9d22368a8acf55ec36edd14af8f9
19 |
20 | PODFILE CHECKSUM: 4269a90155939122582435f9d1610513292926a1
21 |
22 | COCOAPODS: 1.3.1
23 |
--------------------------------------------------------------------------------
/Sources/SwiftyVIPER.h:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftyVIPER.h
3 | // SwiftyVIPER
4 | //
5 | // Created by Cody Winton on 11/16/16.
6 | // Copyright © 2016 codeRed. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for SwiftyVIPER.
12 | FOUNDATION_EXPORT double SwiftyVIPERVersionNumber;
13 |
14 | //! Project version string for SwiftyVIPER.
15 | FOUNDATION_EXPORT const unsigned char SwiftyVIPERVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/SwiftyVIPER.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'SwiftyVIPER'
3 | s.version = '2.0'
4 | s.license = { :type => 'MIT', :file => 'LICENSE' }
5 | s.summary = 'Swifty Interaction with VIPER'
6 | s.homepage = 'https://github.com/codytwinton/SwiftyVIPER'
7 | s.source = { :git => 'https://github.com/codytwinton/SwiftyVIPER.git', :tag => s.version.to_s }
8 |
9 | s.source_files = 'Sources/*.swift'
10 | s.ios.deployment_target = '11.0'
11 | s.tvos.deployment_target = '11.0'
12 | s.frameworks = 'UIKit'
13 | s.requires_arc = true
14 |
15 | s.social_media_url = 'http://twitter.com/codytwinton'
16 | s.authors = { 'Cody Winton' => 'cody.t.winton@gmail.com' }
17 | end
18 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/DetailRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailRouter.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 | import UIKit
16 |
17 | // MARK: Protocols
18 |
19 | protocol DetailPresenterRouterProtocol: PresenterRouterProtocol {
20 |
21 | }
22 |
23 | // MARK: -
24 |
25 | final class DetailRouter: RouterProtocol, DetailPresenterRouterProtocol {
26 |
27 | // MARK: - Variables
28 |
29 | weak var viewController: UIViewController?
30 |
31 | // MARK: - Router Protocol
32 |
33 | // MARK: Detail Presenter to Router Protocol
34 | }
35 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/RootInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootInteractor.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/5/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | protocol RootPresenterInteractorProtocol {
20 | func requestTitle()
21 | }
22 |
23 | // MARK: -
24 |
25 | final class RootInteractor: RootPresenterInteractorProtocol {
26 |
27 | // MARK: - Variables
28 |
29 | weak var presenter: RootInteractorPresenterProtocol?
30 |
31 | // MARK: - Root Presenter to Interactor Protocol
32 |
33 | func requestTitle() {
34 | presenter?.set(title: "Root")
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/DetailInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailInteractor.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 |
16 | // MARK: Protocols
17 |
18 | protocol DetailPresenterInteractorProtocol {
19 | func requestTitle()
20 | }
21 |
22 | // MARK: -
23 |
24 | final class DetailInteractor: DetailPresenterInteractorProtocol {
25 |
26 | // MARK: - Variables
27 |
28 | weak var presenter: DetailInteractorPresenterProtocol?
29 |
30 | // MARK: - Detail Presenter to Interactor Protocol
31 |
32 | func requestTitle() {
33 | presenter?.set(title: "Detail")
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/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 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode9.2
3 |
4 | env:
5 | global:
6 | - LC_CTYPE=en_US.UTF-8
7 | - LANG=en_US.UTF-8
8 | - PROJECT=SwiftyVIPER.xcodeproj
9 | - IOS_FRAMEWORK_SCHEME="SwiftyVIPERiOS"
10 | - IOS_SDK=iphonesimulator11.2
11 | matrix:
12 | - DESTINATION="OS=11.2,name=iPhone 8" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK"
13 |
14 | script:
15 | - brew unlink swiftlint
16 | - brew install swiftlint
17 | - xcodebuild -version
18 | - xcodebuild -showsdks
19 | - xcodebuild -project "$PROJECT" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=YES -enableCodeCoverage YES ENABLE_TESTABILITY=YES build test
20 |
21 | notifications:
22 | email: false
23 |
24 | after_success:
25 | - bash <(curl -s https://codecov.io/bash)
26 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/RootRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootRouter.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/5/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 | import UIKit
16 |
17 | // MARK: Protocols
18 |
19 | protocol RootPresenterRouterProtocol: PresenterRouterProtocol {
20 | func detailsSelected()
21 | }
22 |
23 | // MARK: -
24 |
25 | final class RootRouter: RouterProtocol, RootPresenterRouterProtocol {
26 |
27 | // MARK: - Variables
28 |
29 | weak var viewController: UIViewController?
30 |
31 | // MARK: - Router Protocol
32 |
33 | // MARK: Root Presenter to Router Protocol
34 |
35 | func detailsSelected() {
36 | DetailModule().present(from: viewController, style: .coverVertical)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftyVIPER
4 | //
5 | // Created by Cody Winton on 11/4/16.
6 | // Copyright © 2016 codeRed. All rights reserved.
7 | //
8 |
9 | import SnapKit
10 | import UIKit
11 |
12 | @UIApplicationMain
13 | class AppDelegate: UIResponder, UIApplicationDelegate {
14 |
15 | var window: UIWindow?
16 |
17 | func application(_ application: UIApplication,
18 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
19 |
20 | let rootModule = RootModule()
21 |
22 | window = UIWindow(frame: UIScreen.main.bounds)
23 | window?.rootViewController = rootModule.view
24 | window?.backgroundColor = .white
25 | window?.makeKeyAndVisible()
26 |
27 | // Override point for customization after application launch.
28 | return true
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/DetailRouterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailRouterTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | @testable import SwiftyVIPERExample
14 | import XCTest
15 |
16 | // MARK: -
17 |
18 | class DetailRouterTests: XCTestCase {
19 |
20 | // MARK: - Variables
21 |
22 | private var router: DetailRouter?
23 |
24 | // MARK: Setup
25 |
26 | override func setUp() {
27 | super.setUp()
28 | // Put setup code here. This method is called before the invocation of each test method in the class.
29 |
30 | router = DetailRouter()
31 | }
32 |
33 | override func tearDown() {
34 | // Put teardown code here. This method is called after the invocation of each test method in the class.
35 | super.tearDown()
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
20 | protocol ___VARIABLE_productName___PresenterRouterProtocol: PresenterRouterProtocol {
21 |
22 | }
23 |
24 | // MARK: -
25 |
26 | /// The Router for the ___VARIABLE_productName___ module
27 | final class ___FILEBASENAMEASIDENTIFIER___: RouterProtocol, ___VARIABLE_productName___PresenterRouterProtocol {
28 |
29 | // MARK: - Variables
30 |
31 | weak var viewController: UIViewController?
32 | }
33 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/___FILEBASENAME___Router.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
20 | protocol ___VARIABLE_productName___PresenterRouterProtocol: PresenterRouterProtocol {
21 |
22 | }
23 |
24 | // MARK: -
25 |
26 | /// The Router for the ___VARIABLE_productName___ module
27 | final class ___FILEBASENAMEASIDENTIFIER___: RouterProtocol, ___VARIABLE_productName___PresenterRouterProtocol {
28 |
29 | // MARK: - Variables
30 |
31 | weak var viewController: UIViewController?
32 | }
33 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/RootRouterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootRouterTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class RootRouterTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var router: RootRouter?
24 |
25 | // MARK: Test Functions
26 |
27 | func testDetails() {
28 | router?.detailsSelected()
29 | }
30 |
31 | // MARK: Setup
32 |
33 | override func setUp() {
34 | super.setUp()
35 | // Put setup code here. This method is called before the invocation of each test method in the class.
36 |
37 | router = RootRouter()
38 | }
39 |
40 | override func tearDown() {
41 | // Put teardown code here. This method is called after the invocation of each test method in the class.
42 | super.tearDown()
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/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 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/___FILEBASENAME___RouterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import XCTest
14 |
15 | @testable import ___PROJECTNAME___
16 |
17 | import SwiftyVIPER
18 |
19 | // MARK: -
20 |
21 | class ___FILEBASENAMEASIDENTIFIER___: XCTestCase {
22 |
23 | // MARK: - Variables
24 |
25 | private var router: ___VARIABLE_productName___Router?
26 |
27 | // MARK: Setup
28 |
29 | override func setUp() {
30 | super.setUp()
31 | // Put setup code here. This method is called before the invocation of each test method in the class.
32 |
33 | router = ___VARIABLE_productName___Router()
34 | }
35 |
36 | override func tearDown() {
37 | // Put teardown code here. This method is called after the invocation of each test method in the class.
38 | super.tearDown()
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/RootModule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootModule.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/5/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | import UIKit
15 |
16 | // MARK: -
17 |
18 | final class RootModule: ModuleProtocol {
19 |
20 | // MARK: - Variables
21 |
22 | private(set) lazy var interactor: RootInteractor = {
23 | RootInteractor()
24 | }()
25 |
26 | private(set) lazy var router: RootRouter = {
27 | RootRouter()
28 | }()
29 |
30 | private(set) lazy var presenter: RootPresenter = {
31 | RootPresenter(router: self.router, interactor: self.interactor)
32 | }()
33 |
34 | private(set) lazy var view: RootViewController = {
35 | RootViewController(presenter: self.presenter)
36 | }()
37 |
38 | // MARK: Module Protocol Variables
39 |
40 | var viewController: UIViewController {
41 | return view
42 | }
43 |
44 | // MARK: Inits
45 |
46 | init() {
47 | presenter.view = view
48 | router.viewController = view
49 | interactor.presenter = presenter
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Cody Winton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/___FILEBASENAME___Interactor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 |
16 | // MARK: Protocols
17 |
18 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
19 | protocol ___VARIABLE_productName___PresenterInteractorProtocol {
20 | /// Requests the title for the presenter
21 | func requestTitle()
22 | }
23 |
24 | // MARK: -
25 |
26 | /// The Interactor for the ___VARIABLE_productName___ module
27 | final class ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_productName___PresenterInteractorProtocol {
28 |
29 | // MARK: - Variables
30 |
31 | weak var presenter: ___FILEBASENAMEASIDENTIFIER___PresenterProtocol?
32 |
33 | // MARK: - ___VARIABLE_productName___ Presenter to Interactor Protocol
34 |
35 | func requestTitle() {
36 | presenter?.set(title: "___VARIABLE_productName___")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/___FILEBASENAME___Interactor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 |
16 | // MARK: Protocols
17 |
18 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
19 | protocol ___VARIABLE_productName___PresenterInteractorProtocol {
20 | /// Requests the title for the presenter
21 | func requestTitle()
22 | }
23 |
24 | // MARK: -
25 |
26 | /// The Interactor for the ___VARIABLE_productName___ module
27 | final class ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_productName___PresenterInteractorProtocol {
28 |
29 | // MARK: - Variables
30 |
31 | weak var presenter: ___FILEBASENAMEASIDENTIFIER___PresenterProtocol?
32 |
33 | // MARK: - ___VARIABLE_productName___ Presenter to Interactor Protocol
34 |
35 | func requestTitle() {
36 | presenter?.set(title: "___VARIABLE_productName___")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Tests/MockModule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MockModule.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Test
6 | //
7 | // By Cody Winton 11/7/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 | import UIKit
16 |
17 | // MARK: -
18 |
19 | /// Used to initialize the Test VIPER module
20 | class MockModule: ModuleProtocol {
21 |
22 | // MARK: - Variables
23 |
24 | private(set) lazy var router: MockRouter = {
25 | MockRouter()
26 | }()
27 |
28 | private(set) lazy var view: UIViewController = {
29 | UIViewController()
30 | }()
31 |
32 | var viewController: UIViewController {
33 | return view
34 | }
35 |
36 | init() {
37 | router.viewController = view
38 | }
39 | }
40 |
41 | // MARK: -
42 |
43 | /// The Router for the Test module
44 | class MockRouter: RouterProtocol, PresenterRouterProtocol {
45 |
46 | // MARK: - Variables
47 |
48 | weak var viewController: UIViewController?
49 | }
50 |
51 | // MARK: - Mock Classes
52 |
53 | // MARK: -
54 |
55 | class MockPresenter: ViewPresenterProtocol {
56 | func viewLoaded() {}
57 | }
58 |
59 | // MARK: -
60 |
61 | class MockViewController: UIViewController, StoryboardIdentifiable {}
62 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/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 | UIRequiredDeviceCapabilities
26 |
27 | armv7
28 |
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/DetailModule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailModule.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 | import SwiftyVIPER
15 | import UIKit
16 |
17 | // MARK: -
18 |
19 | final class DetailModule: ModuleProtocol {
20 |
21 | // MARK: - Constants
22 |
23 | let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
24 |
25 | // MARK: Variables
26 |
27 | private(set) lazy var interactor: DetailInteractor = {
28 | DetailInteractor()
29 | }()
30 |
31 | private(set) lazy var router: DetailRouter = {
32 | DetailRouter()
33 | }()
34 |
35 | private(set) lazy var presenter: DetailPresenter = {
36 | DetailPresenter(router: self.router, interactor: self.interactor)
37 | }()
38 |
39 | private(set) lazy var view: DetailViewController = {
40 | let vc = self.storyboard.viewController(DetailViewController.self)
41 | vc.presenter = self.presenter
42 | return vc
43 | }()
44 |
45 | // MARK: - Module Protocol Variables
46 |
47 | var viewController: UIViewController { return view }
48 |
49 | // MARK: Inits
50 |
51 | init() {
52 | presenter.view = view
53 | router.viewController = view
54 | interactor.presenter = presenter
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/___FILEBASENAME___ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
20 | protocol ___VARIABLE_productName___PresenterViewProtocol: class {
21 | /** Sets the title for the view
22 | - parameters:
23 | - title The title to set
24 | */
25 | func set(title: String?)
26 | }
27 |
28 | // MARK: -
29 |
30 | /// The View Controller for the ___VARIABLE_productName___ module
31 | class ___FILEBASENAMEASIDENTIFIER___: UIViewController, StoryboardIdentifiable, ___VARIABLE_productName___PresenterViewProtocol {
32 |
33 | // MARK: - Constants
34 |
35 | // MARK: Variables
36 |
37 | var presenter: ___VARIABLE_productName___ViewPresenterProtocol?
38 |
39 | // MARK: - Load Functions
40 |
41 | override func viewDidLoad() {
42 | super.viewDidLoad()
43 | presenter?.viewLoaded()
44 |
45 | view.backgroundColor = .white
46 | }
47 |
48 | // MARK: - ___VARIABLE_productName___ Presenter to View Protocol
49 |
50 | func set(title: String?) {
51 | self.title = title
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/___FILEBASENAME___Module.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | import UIKit
15 |
16 | // MARK: -
17 |
18 | /// Used to initialize the ___VARIABLE_productName___ VIPER module
19 | final class ___FILEBASENAMEASIDENTIFIER___: ModuleProtocol {
20 |
21 | // MARK: - Variables
22 |
23 | private(set) lazy var interactor: ___VARIABLE_productName___Interactor = {
24 | ___VARIABLE_productName___Interactor()
25 | }()
26 |
27 | private(set) lazy var router: ___VARIABLE_productName___Router = {
28 | ___VARIABLE_productName___Router()
29 | }()
30 |
31 | private(set) lazy var presenter: ___VARIABLE_productName___Presenter = {
32 | ___VARIABLE_productName___Presenter(router: self.router, interactor: self.interactor)
33 | }()
34 |
35 | private(set) lazy var view: ___VARIABLE_productName___ViewController = {
36 | ___VARIABLE_productName___ViewController(presenter: self.presenter)
37 | }()
38 |
39 | // MARK: - Module Protocol Variables
40 |
41 | var viewController: UIViewController {
42 | return view
43 | }
44 |
45 | // MARK: Inits
46 |
47 | init() {
48 | presenter.view = view
49 | router.viewController = view
50 | interactor.presenter = presenter
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/DetailViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailViewController.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | import UIKit
15 |
16 | // MARK: Protocols
17 |
18 | protocol DetailPresenterViewProtocol: class {
19 | func set(title: String?)
20 | }
21 |
22 | // MARK: -
23 |
24 | class DetailViewController: UIViewController, StoryboardIdentifiable, DetailPresenterViewProtocol {
25 |
26 | // MARK: - Constants
27 |
28 | // MARK: Variables
29 |
30 | var presenter: DetailViewPresenterProtocol?
31 |
32 | @IBOutlet weak private(set) var titleLabel: UILabel? {
33 | willSet(label) {
34 | label?.textAlignment = .center
35 | }
36 | }
37 |
38 | @IBOutlet weak private(set) var closeButton: UIButton? {
39 | willSet(button) {
40 | button?.setTitle("Close", for: .normal)
41 | button?.addTarget(self, action: #selector(closeSelected), for: .touchUpInside)
42 | }
43 | }
44 |
45 | // MARK: - Functions
46 |
47 | @objc
48 | func closeSelected() {
49 | presenter?.closeSelected()
50 | }
51 |
52 | // MARK: - Load Functions
53 |
54 | override func viewDidLoad() {
55 | super.viewDidLoad()
56 | presenter?.viewLoaded()
57 |
58 | view.backgroundColor = .white
59 | }
60 |
61 | // MARK: - Detail Presenter to View Protocol
62 |
63 | func set(title: String?) {
64 | titleLabel?.text = title
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/RootModuleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootModuleTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class RootModuleTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | var module: RootModule?
24 |
25 | // MARK: Test Functions
26 |
27 | func testSetup() {
28 | XCTAssertNotNil(module)
29 |
30 | XCTAssertNotNil(module?.interactor)
31 | XCTAssertNotNil(module?.router)
32 | XCTAssertNotNil(module?.presenter)
33 | XCTAssertNotNil(module?.view)
34 | XCTAssertNotNil(module?.viewController)
35 |
36 | XCTAssertNotNil(module?.view.presenter)
37 |
38 | XCTAssertNotNil(module?.presenter.view)
39 | XCTAssertNotNil(module?.presenter.router)
40 | XCTAssertNotNil(module?.presenter.interactor)
41 |
42 | XCTAssertNotNil(module?.router.viewController)
43 |
44 | XCTAssertNotNil(module?.interactor.presenter)
45 | }
46 |
47 | // MARK: Setup
48 |
49 | override func setUp() {
50 | super.setUp()
51 | // Put setup code here. This method is called before the invocation of each test method in the class.
52 |
53 | module = RootModule()
54 | }
55 |
56 | override func tearDown() {
57 | // Put teardown code here. This method is called after the invocation of each test method in the class.
58 | super.tearDown()
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/DetailInteractorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailInteractorTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | @testable import SwiftyVIPERExample
14 | import XCTest
15 |
16 | // MARK: -
17 |
18 | class DetailInteractorTests: XCTestCase {
19 |
20 | // MARK: - Variables
21 |
22 | private var presenter: MockPresenter?
23 | private var interactor: DetailInteractor?
24 |
25 | // MARK: Test Functions
26 |
27 | func testPresenter() {
28 | interactor?.requestTitle()
29 | XCTAssertEqual(presenter?.title, "Detail")
30 | }
31 |
32 | // MARK: Setup
33 |
34 | override func setUp() {
35 | super.setUp()
36 | // Put setup code here. This method is called before the invocation of each test method in the class.
37 |
38 | presenter = MockPresenter()
39 |
40 | interactor = DetailInteractor()
41 | interactor?.presenter = self.presenter
42 | }
43 |
44 | override func tearDown() {
45 | // Put teardown code here. This method is called after the invocation of each test method in the class.
46 | super.tearDown()
47 | }
48 | }
49 |
50 | // MARK: - Mock Classes
51 |
52 | // MARK: -
53 |
54 | private class MockPresenter: DetailInteractorPresenterProtocol {
55 |
56 | // MARK: Variables
57 |
58 | var title: String?
59 |
60 | // MARK: Functions
61 |
62 | func set(title: String?) {
63 | self.title = title
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/RootInteractorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootInteractorTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class RootInteractorTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var presenter: MockPresenter?
24 | private var interactor: RootInteractor?
25 |
26 | // MARK: Test Functions
27 |
28 | func testPresenter() {
29 | interactor?.requestTitle()
30 | XCTAssertEqual(presenter?.title, "Root")
31 | }
32 |
33 | // MARK: Setup
34 |
35 | override func setUp() {
36 | super.setUp()
37 | // Put setup code here. This method is called before the invocation of each test method in the class.
38 |
39 | presenter = MockPresenter()
40 |
41 | interactor = RootInteractor()
42 | interactor?.presenter = presenter
43 | }
44 |
45 | override func tearDown() {
46 | // Put teardown code here. This method is called after the invocation of each test method in the class.
47 | super.tearDown()
48 | }
49 | }
50 |
51 | // MARK: - Mock Classes
52 |
53 | // MARK: -
54 |
55 | private class MockPresenter: RootInteractorPresenterProtocol {
56 |
57 | // MARK: Variables
58 |
59 | var title: String?
60 |
61 | // MARK: Functions
62 |
63 | func set(title: String?) {
64 | self.title = title
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/DetailModuleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailModuleTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class DetailModuleTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | var module: DetailModule?
24 |
25 | // MARK: Test Functions
26 |
27 | func testSetup() {
28 | XCTAssertNotNil(module)
29 |
30 | XCTAssertNotNil(module?.interactor)
31 | XCTAssertNotNil(module?.router)
32 | XCTAssertNotNil(module?.presenter)
33 | XCTAssertNotNil(module?.view)
34 | XCTAssertNotNil(module?.viewController)
35 |
36 | XCTAssertNotNil(module?.view.presenter)
37 |
38 | XCTAssertNotNil(module?.presenter.view)
39 | XCTAssertNotNil(module?.presenter.router)
40 | XCTAssertNotNil(module?.presenter.interactor)
41 |
42 | XCTAssertNotNil(module?.router.viewController)
43 |
44 | XCTAssertNotNil(module?.interactor.presenter)
45 | }
46 |
47 | // MARK: Setup
48 |
49 | override func setUp() {
50 | super.setUp()
51 | // Put setup code here. This method is called before the invocation of each test method in the class.
52 |
53 | module = DetailModule()
54 | }
55 |
56 | override func tearDown() {
57 | // Put teardown code here. This method is called after the invocation of each test method in the class.
58 | super.tearDown()
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/RootPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootPresenter.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/5/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | protocol RootViewPresenterProtocol: ViewPresenterProtocol {
20 | func detailsSelected()
21 | }
22 |
23 | protocol RootInteractorPresenterProtocol: class {
24 | func set(title: String?)
25 | }
26 |
27 | // MARK: -
28 |
29 | final class RootPresenter: RootViewPresenterProtocol, RootInteractorPresenterProtocol {
30 |
31 | // MARK: - Constants
32 |
33 | let router: RootPresenterRouterProtocol
34 | let interactor: RootPresenterInteractorProtocol
35 |
36 | // MARK: Variables
37 |
38 | weak var view: RootPresenterViewProtocol?
39 |
40 | // MARK: Inits
41 |
42 | init(router: RootPresenterRouterProtocol, interactor: RootPresenterInteractorProtocol) {
43 | self.router = router
44 | self.interactor = interactor
45 | }
46 |
47 | // MARK: - Root View to Presenter Protocol
48 |
49 | func viewLoaded() {
50 | interactor.requestTitle()
51 | }
52 |
53 | func viewAppearing() {
54 |
55 | }
56 |
57 | func viewAppeared() {
58 |
59 | }
60 |
61 | func viewDisappeared() {
62 |
63 | }
64 |
65 | func detailsSelected() {
66 | router.detailsSelected()
67 | }
68 |
69 | // MARK: Root Interactor to Presenter Protocol
70 |
71 | func set(title: String?) {
72 | view?.set(title: title)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/DetailPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailPresenter.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import Foundation
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | protocol DetailViewPresenterProtocol: ViewPresenterProtocol {
20 | func closeSelected()
21 | }
22 |
23 | protocol DetailInteractorPresenterProtocol: class {
24 | func set(title: String?)
25 | }
26 |
27 | // MARK: -
28 |
29 | final class DetailPresenter: DetailViewPresenterProtocol, DetailInteractorPresenterProtocol {
30 |
31 | // MARK: - Constants
32 |
33 | let router: DetailPresenterRouterProtocol
34 | let interactor: DetailPresenterInteractorProtocol
35 |
36 | // MARK: Variables
37 |
38 | weak var view: DetailPresenterViewProtocol?
39 |
40 | // MARK: Inits
41 |
42 | init(router: DetailPresenterRouterProtocol, interactor: DetailPresenterInteractorProtocol) {
43 | self.router = router
44 | self.interactor = interactor
45 | }
46 |
47 | // MARK: - Detail View to Presenter Protocol
48 |
49 | func viewLoaded() {
50 | interactor.requestTitle()
51 | }
52 |
53 | func viewAppearing() {
54 |
55 | }
56 |
57 | func viewAppeared() {
58 |
59 | }
60 |
61 | func viewDisappeared() {
62 |
63 | }
64 |
65 | func closeSelected() {
66 | router.dismiss(completion: nil)
67 | }
68 |
69 | // MARK: Detail Interactor to Presenter Protocol
70 |
71 | func set(title: String?) {
72 | view?.set(title: title)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AllowedTypes
6 |
7 | public.swift-source
8 |
9 | Platforms
10 |
11 | com.apple.platform.iphoneos
12 |
13 | DefaultCompletionName
14 | NewVIPERModule
15 | Description
16 | VIPER Module template, including View, Presenter, Router, and Interactor with protocols
17 | Kind
18 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
19 | MainTemplateFile
20 | ___FILEBASENAME___
21 | SortOrder
22 | 1
23 | Options
24 |
25 |
26 | Default
27 |
28 | Description
29 | The name of the VIPER module, in CamelStyle
30 | Identifier
31 | viperModuleName
32 | Name
33 | Module Name
34 | Required
35 | YES
36 | Type
37 | text
38 |
39 |
40 | Default
41 | ___VARIABLE_viperModuleName___
42 | Identifier
43 | productName
44 | Type
45 | static
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AllowedTypes
6 |
7 | public.swift-source
8 |
9 | Platforms
10 |
11 | com.apple.platform.iphoneos
12 |
13 | DefaultCompletionName
14 | NewVIPERModule
15 | Description
16 | VIPER Module template, including View, Presenter, Router, and Interactor with protocols
17 | Kind
18 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
19 | MainTemplateFile
20 | ___FILEBASENAME___
21 | SortOrder
22 | 1
23 | Options
24 |
25 |
26 | Default
27 |
28 | Description
29 | The name of the VIPER module, in CamelStyle
30 | Identifier
31 | viperModuleName
32 | Name
33 | Module Name
34 | Required
35 | YES
36 | Type
37 | text
38 |
39 |
40 | Default
41 | ___VARIABLE_viperModuleName___
42 | Identifier
43 | productName
44 | Type
45 | static
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/TemplateInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AllowedTypes
6 |
7 | public.swift-source
8 |
9 | Platforms
10 |
11 | com.apple.platform.iphoneos
12 |
13 | DefaultCompletionName
14 | NewVIPERModule
15 | Description
16 | VIPER Module template, including View, Presenter, Router, and Interactor with protocols
17 | Kind
18 | Xcode.IDEKit.TextSubstitutionFileTemplateKind
19 | MainTemplateFile
20 | ___FILEBASENAME___
21 | SortOrder
22 | 1
23 | Options
24 |
25 |
26 | Default
27 |
28 | Description
29 | The name of the VIPER module, in CamelStyle
30 | Identifier
31 | viperModuleName
32 | Name
33 | Module Name
34 | Required
35 | YES
36 | Type
37 | text
38 |
39 |
40 | Default
41 | ___VARIABLE_viperModuleName___
42 | Identifier
43 | productName
44 | Type
45 | static
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/___FILEBASENAME___ModuleTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | @testable import ___PROJECTNAME___
14 |
15 | import SwiftyVIPER
16 | import XCTest
17 |
18 | // MARK: -
19 |
20 | class ___FILEBASENAMEASIDENTIFIER___: XCTestCase {
21 |
22 | // MARK: - Variables
23 |
24 | var module: ___VARIABLE_productName___Module?
25 |
26 | // MARK: Test Functions
27 |
28 | func testSetup() {
29 | XCTAssertNotNil(module)
30 |
31 | XCTAssertNotNil(module?.interactor)
32 | XCTAssertNotNil(module?.router)
33 | XCTAssertNotNil(module?.presenter)
34 | XCTAssertNotNil(module?.view)
35 | XCTAssertNotNil(module?.viewController)
36 |
37 | XCTAssertNotNil(module?.view.presenter)
38 |
39 | XCTAssertNotNil(module?.presenter.view)
40 | XCTAssertNotNil(module?.presenter.router)
41 | XCTAssertNotNil(module?.presenter.interactor)
42 |
43 | XCTAssertNotNil(module?.router.viewController)
44 |
45 | XCTAssertNotNil(module?.interactor.presenter)
46 | }
47 |
48 | // MARK: Setup
49 |
50 | override func setUp() {
51 | super.setUp()
52 | // Put setup code here. This method is called before the invocation of each test method in the class.
53 |
54 | module = ___VARIABLE_productName___Module()
55 | }
56 |
57 | override func tearDown() {
58 | // Put teardown code here. This method is called after the invocation of each test method in the class.
59 | super.tearDown()
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/___FILEBASENAME___Module.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | import UIKit
15 |
16 | // MARK: -
17 |
18 | /// Used to initialize the ___VARIABLE_productName___ VIPER module
19 | final class ___FILEBASENAMEASIDENTIFIER___: ModuleProtocol {
20 |
21 | // MARK: - Constants
22 |
23 | let storyboard: UIStoryboard = UIStoryboard(name: <#T##String#>, bundle: Bundle.main)
24 |
25 | // MARK: Variables
26 |
27 | private(set) lazy var interactor: ___VARIABLE_productName___Interactor = {
28 | ___VARIABLE_productName___Interactor()
29 | }()
30 |
31 | private(set) lazy var router: ___VARIABLE_productName___Router = {
32 | ___VARIABLE_productName___Router()
33 | }()
34 |
35 | private(set) lazy var presenter: ___VARIABLE_productName___Presenter = {
36 | ___VARIABLE_productName___Presenter(router: self.router, interactor: self.interactor)
37 | }()
38 |
39 | private(set) lazy var view: ___VARIABLE_productName___ViewController = {
40 | var vc = self.storyboard.viewController(___VARIABLE_productName___ViewController.self)
41 | vc.presenter = self.presenter
42 | return vc
43 | }()
44 |
45 | // MARK: - Module Protocol Variables
46 |
47 | var viewController: UIViewController {
48 | return view
49 | }
50 |
51 | // MARK: Inits
52 |
53 | init() {
54 | presenter.view = view
55 | router.viewController = view
56 | interactor.presenter = presenter
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 |
20 | ## Other
21 | *.xccheckout
22 | *.moved-aside
23 | *.xcuserstate
24 | *.xcscmblueprint
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 |
30 | ## Playgrounds
31 | timeline.xctimeline
32 | playground.xcworkspace
33 |
34 | # Swift Package Manager
35 | #
36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
37 | # Packages/
38 | .build/
39 |
40 | # CocoaPods
41 | #
42 | # We recommend against adding the Pods directory to your .gitignore. However
43 | # you should judge for yourself, the pros and cons are mentioned at:
44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
45 | #
46 | Pods
47 | Pods/*
48 |
49 | # Carthage
50 | #
51 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
52 | # Carthage/Checkouts
53 |
54 | Carthage/Build
55 |
56 | # fastlane
57 | #
58 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
59 | # screenshots whenever they are needed.
60 | # For more information about the recommended setup visit:
61 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
62 |
63 | fastlane/report.xml
64 | fastlane/screenshots
65 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/___FILEBASENAME___InteractorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | @testable import ___PROJECTNAME___
14 |
15 | import SwiftyVIPER
16 | import XCTest
17 |
18 | // MARK: -
19 |
20 | class ___FILEBASENAMEASIDENTIFIER___: XCTestCase {
21 |
22 | // MARK: - Variables
23 |
24 | private var presenter: MockPresenter?
25 | private var interactor: ___VARIABLE_productName___Interactor?
26 |
27 | // MARK: Test Functions
28 |
29 | func testPresenter() {
30 | interactor?.requestTitle()
31 | XCTAssertEqual(presenter?.title, "___VARIABLE_productName___")
32 | }
33 |
34 | // MARK: Setup
35 |
36 | override func setUp() {
37 | super.setUp()
38 | // Put setup code here. This method is called before the invocation of each test method in the class.
39 |
40 | presenter = MockPresenter()
41 |
42 | interactor = ___VARIABLE_productName___Interactor()
43 | interactor?.presenter = presenter
44 | }
45 |
46 | override func tearDown() {
47 | // Put teardown code here. This method is called after the invocation of each test method in the class.
48 | super.tearDown()
49 | }
50 | }
51 |
52 | // MARK: - Mock Classes
53 |
54 | // MARK: -
55 |
56 | private class MockPresenter: ___VARIABLE_productName___InteractorPresenterProtocol {
57 |
58 | // MARK: Variables
59 |
60 | var title: String?
61 |
62 | // MARK: Functions
63 |
64 | func set(title: String?) {
65 | self.title = title
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/___FILEBASENAME___ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Presenter`
20 | protocol ___VARIABLE_productName___PresenterViewProtocol: class {
21 | /** Sets the title for the view
22 | - parameters:
23 | - title The title to set
24 | */
25 | func set(title: String?)
26 | }
27 |
28 | // MARK: -
29 |
30 | /// The View Controller for the ___VARIABLE_productName___ module
31 | class ___FILEBASENAMEASIDENTIFIER___: UIViewController, ___VARIABLE_productName___PresenterViewProtocol {
32 |
33 | // MARK: - Constants
34 |
35 | let presenter: ___VARIABLE_productName___ViewPresenterProtocol
36 |
37 | // MARK: Variables
38 |
39 | // MARK: Inits
40 |
41 | init(presenter: ___VARIABLE_productName___ViewPresenterProtocol) {
42 | self.presenter = presenter
43 | super.init(nibName: nil, bundle: nil)
44 | }
45 |
46 | required init?(coder aDecoder: NSCoder) {
47 | fatalError("init(coder:) has not been implemented")
48 | }
49 |
50 | // MARK: - Load Functions
51 |
52 | override func viewDidLoad() {
53 | super.viewDidLoad()
54 | presenter.viewLoaded()
55 |
56 | view.backgroundColor = .white
57 | }
58 |
59 | // MARK: - ___VARIABLE_productName___ Presenter to View Protocol
60 |
61 | func set(title: String?) {
62 | self.title = title
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/RootViewTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootViewTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class RootViewTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var presenter: MockPresenter?
24 | private var view: RootViewController?
25 |
26 | // MARK: Test Functions
27 |
28 | func testPresenter() {
29 | view?.beginAppearanceTransition(true, animated: false)
30 | view?.endAppearanceTransition()
31 | XCTAssert(presenter?.isViewLoaded ?? false)
32 |
33 | view?.detailsSelected()
34 | XCTAssert(presenter?.isDetailsSelected ?? false)
35 |
36 | view?.set(title: "Root")
37 | XCTAssertEqual(view?.title, "Root")
38 | }
39 |
40 | // MARK: Setup
41 |
42 | override func setUp() {
43 | super.setUp()
44 | // Put setup code here. This method is called before the invocation of each test method in the class.
45 |
46 | let presenter = MockPresenter()
47 | self.presenter = presenter
48 | view = RootViewController(presenter: presenter)
49 | }
50 |
51 | override func tearDown() {
52 | // Put teardown code here. This method is called after the invocation of each test method in the class.
53 | super.tearDown()
54 | }
55 | }
56 |
57 | // MARK: - Mock Classes
58 |
59 | // MARK: -
60 |
61 | private class MockPresenter: RootViewPresenterProtocol {
62 |
63 | // MARK: Variables
64 |
65 | var isViewLoaded: Bool = false
66 |
67 | var isDetailsSelected: Bool = false
68 |
69 | // MARK: Functions
70 |
71 | func viewLoaded() {
72 | isViewLoaded = true
73 | }
74 |
75 | func detailsSelected() {
76 | isDetailsSelected = true
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/DetailViewTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailViewControllerTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class DetailViewTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var presenter: MockPresenter?
24 | private var view: DetailViewController?
25 |
26 | // MARK: Test Functions
27 |
28 | func testPresenter() {
29 | view?.beginAppearanceTransition(true, animated: false)
30 | view?.endAppearanceTransition()
31 | XCTAssert(presenter?.isViewLoaded ?? false)
32 |
33 | view?.closeSelected()
34 | XCTAssert(presenter?.closeCalled ?? false)
35 |
36 | view?.set(title: "Detail")
37 | XCTAssertEqual(view?.titleLabel?.text, "Detail")
38 | }
39 |
40 | // MARK: Setup
41 |
42 | override func setUp() {
43 | super.setUp()
44 | // Put setup code here. This method is called before the invocation of each test method in the class.
45 |
46 | presenter = MockPresenter()
47 |
48 | let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
49 | view = storyboard.viewController(DetailViewController.self)
50 | view?.presenter = presenter
51 | }
52 |
53 | override func tearDown() {
54 | // Put teardown code here. This method is called after the invocation of each test method in the class.
55 | super.tearDown()
56 | }
57 | }
58 |
59 | // MARK: - Mock Classes
60 |
61 | // MARK: -
62 |
63 | private class MockPresenter: DetailViewPresenterProtocol {
64 |
65 | // MARK: Variables
66 |
67 | var isViewLoaded: Bool = false
68 |
69 | var closeCalled: Bool = false
70 |
71 | // MARK: Functions
72 |
73 | func viewLoaded() {
74 | isViewLoaded = true
75 | }
76 |
77 | func closeSelected() {
78 | closeCalled = true
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Tests/tvOS.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 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module.xctemplate/___FILEBASENAME___Presenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___ViewController`
20 | protocol ___VARIABLE_productName___ViewPresenterProtocol: ViewPresenterProtocol {
21 |
22 | }
23 |
24 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Interactor`
25 | protocol ___VARIABLE_productName___InteractorPresenterProtocol: class {
26 | /** Sets the title for the presenter
27 | - parameters:
28 | - title The title to set
29 | */
30 | func set(title: String?)
31 | }
32 |
33 | // MARK: -
34 |
35 | /// The Presenter for the ___VARIABLE_productName___ module
36 | final class ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_productName___ViewPresenterProtocol, ___VARIABLE_productName___InteractorPresenterProtocol {
37 |
38 | // MARK: - Constants
39 |
40 | let router: ___FILEBASENAMEASIDENTIFIER___RouterProtocol
41 | let interactor: ___FILEBASENAMEASIDENTIFIER___InteractorProtocol
42 |
43 | // MARK: Variables
44 |
45 | weak var view: ___FILEBASENAMEASIDENTIFIER___ViewProtocol?
46 |
47 | // MARK: Inits
48 |
49 | init(router: ___FILEBASENAMEASIDENTIFIER___RouterProtocol, interactor: ___FILEBASENAMEASIDENTIFIER___InteractorProtocol) {
50 | self.router = router
51 | self.interactor = interactor
52 | }
53 |
54 | // MARK: - ___VARIABLE_productName___ View to Presenter Protocol
55 |
56 | func viewLoaded() {
57 | interactor.requestTitle()
58 | }
59 |
60 | // MARK: - ___VARIABLE_productName___ Interactor to Presenter Protocol
61 |
62 | func set(title: String?) {
63 | view?.set(title: title)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Storyboard.xctemplate/___FILEBASENAME___Presenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import UIKit
14 |
15 | import SwiftyVIPER
16 |
17 | // MARK: Protocols
18 |
19 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___ViewController`
20 | protocol ___VARIABLE_productName___ViewPresenterProtocol: ViewPresenterProtocol {
21 |
22 | }
23 |
24 | /// Should be conformed to by the `___FILEBASENAMEASIDENTIFIER___` and referenced by `___VARIABLE_productName___Interactor`
25 | protocol ___VARIABLE_productName___InteractorPresenterProtocol: class {
26 | /** Sets the title for the presenter
27 | - parameters:
28 | - title The title to set
29 | */
30 | func set(title: String?)
31 | }
32 |
33 | // MARK: -
34 |
35 | /// The Presenter for the ___VARIABLE_productName___ module
36 | final class ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_productName___ViewPresenterProtocol, ___VARIABLE_productName___InteractorPresenterProtocol {
37 |
38 | // MARK: - Constants
39 |
40 | let router: ___FILEBASENAMEASIDENTIFIER___RouterProtocol
41 | let interactor: ___FILEBASENAMEASIDENTIFIER___InteractorProtocol
42 |
43 | // MARK: Variables
44 |
45 | weak var view: ___FILEBASENAMEASIDENTIFIER___ViewProtocol?
46 |
47 | // MARK: Inits
48 |
49 | init(router: ___FILEBASENAMEASIDENTIFIER___RouterProtocol, interactor: ___FILEBASENAMEASIDENTIFIER___InteractorProtocol) {
50 | self.router = router
51 | self.interactor = interactor
52 | }
53 |
54 | // MARK: - ___VARIABLE_productName___ View to Presenter Protocol
55 |
56 | func viewLoaded() {
57 | interactor.requestTitle()
58 | }
59 |
60 | // MARK: - ___VARIABLE_productName___ Interactor to Presenter Protocol
61 |
62 | func set(title: String?) {
63 | view?.set(title: title)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Tests/iOS.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 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/Modules/RootViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootViewController.swift
3 | // Project: SwiftyVIPER
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/5/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | import UIKit
15 |
16 | // MARK: Protocols
17 |
18 | protocol RootPresenterViewProtocol: class {
19 | func set(title: String?)
20 | }
21 |
22 | // MARK: -
23 |
24 | class RootViewController: UIViewController, RootPresenterViewProtocol {
25 |
26 | // MARK: - Constants
27 |
28 | let presenter: RootViewPresenterProtocol
29 |
30 | // MARK: Variables
31 |
32 | lazy var rootImageView: UIImageView = {
33 | let imageView = UIImageView(image: #imageLiteral(resourceName: "SwiftyVIPER"))
34 | imageView.contentMode = .scaleAspectFit
35 | return imageView
36 | }()
37 |
38 | lazy var detailsButton: UIButton = {
39 | let button = UIButton(type: .system)
40 | button.frame = CGRect(x: 0, y: 0, width: 100, height: 50)
41 | button.setTitle("Show Details", for: .normal)
42 | button.addTarget(self, action: #selector(detailsSelected), for: .touchUpInside)
43 | return button
44 | }()
45 |
46 | // MARK: Inits
47 |
48 | init(presenter: RootViewPresenterProtocol) {
49 | self.presenter = presenter
50 | super.init(nibName: nil, bundle: nil)
51 | }
52 |
53 | required init?(coder aDecoder: NSCoder) {
54 | fatalError("init(coder:) has not been implemented")
55 | }
56 |
57 | // MARK: - Functions
58 |
59 | @objc
60 | func detailsSelected() {
61 | presenter.detailsSelected()
62 | }
63 |
64 | // MARK: - Load Functions
65 |
66 | override func viewDidLoad() {
67 | super.viewDidLoad()
68 | presenter.viewLoaded()
69 |
70 | view.backgroundColor = .white
71 |
72 | view.addSubview(rootImageView)
73 | rootImageView.snp.makeConstraints { make in
74 | make.top.equalTo(40)
75 | make.centerX.equalTo(self.view)
76 | make.left.equalTo(self.view).offset(30)
77 | make.height.equalTo(150)
78 | }
79 |
80 | view.addSubview(detailsButton)
81 | detailsButton.snp.makeConstraints { make in
82 | make.bottom.equalTo(self.view).offset(-30)
83 | make.centerX.equalTo(self.view)
84 | make.size.equalTo(self.detailsButton.frame.size)
85 | }
86 | }
87 |
88 | // MARK: - Root Presenter to View Protocol
89 |
90 | func set(title: String?) {
91 | self.title = title
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Sources/Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // SwiftyVIPER
4 | //
5 | // Created by Cody Winton on 11/8/16.
6 | // Copyright © 2016 codeRed. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: Extensions
12 |
13 | public extension UIStoryboard {
14 |
15 | /**
16 | Returns the view controller of a perticular type
17 |
18 | - parameter type: The Class Type, which must be a `UIViewController` that conforms to `StoryboardIdentifiable`
19 | - returns: A Storyboard Instance of Type
20 | */
21 | func viewController(_ type: T.Type) -> T where T: StoryboardIdentifiable {
22 | guard let vc = instantiateViewController(withIdentifier: type.storyboardID) as? T else {
23 | fatalError("Couldn't find a View Controller with Identifier \(type.storyboardID)")
24 | }
25 | return vc
26 | }
27 | }
28 |
29 | public extension StoryboardIdentifiable where Self: UIViewController {
30 | /// The Storyboard ID to use for a View Controller
31 | static var storyboardID: String {
32 | return String(describing: self)
33 | }
34 | }
35 |
36 | public extension ModuleProtocol {
37 |
38 | func present(from fromVC: UIViewController?, style: UIModalTransitionStyle, completion: CodeBlock? = nil) {
39 | viewController.modalTransitionStyle = style
40 | fromVC?.present(viewController, animated: true, completion: completion)
41 | }
42 |
43 | func push(from navController: UINavigationController?) {
44 | navController?.pushViewController(viewController, animated: true)
45 | }
46 | }
47 |
48 | public extension PresenterRouterProtocol where Self:RouterProtocol {
49 |
50 | func present(_ view: UIViewController, completion: CodeBlock?) {
51 | switch viewController {
52 | case nil:
53 | completion?()
54 | case let controller?:
55 | controller.present(view, animated: true, completion: completion)
56 | }
57 | }
58 |
59 | func dismiss(completion: CodeBlock? = nil) {
60 | switch viewController {
61 | case nil:
62 | completion?()
63 | case let controller?:
64 | controller.view?.endEditing(true)
65 | controller.dismiss(animated: true, completion: completion)
66 | }
67 | }
68 |
69 | @discardableResult
70 | func pop() -> UIViewController? {
71 | return viewController?.navigationController?.popViewController(animated: true)
72 | }
73 | }
74 |
75 | // Allows these functions to be optional
76 | public extension ViewPresenterProtocol {
77 | func viewAppearing() {}
78 | func viewAppeared() {}
79 | func viewDisappeared() {}
80 | }
81 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/___FILEBASENAME___ViewTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import XCTest
14 |
15 | @testable import ___PROJECTNAME___
16 |
17 | import SwiftyVIPER
18 |
19 | // MARK: -
20 |
21 | class ___FILEBASENAMEASIDENTIFIER___: XCTestCase {
22 |
23 | // MARK: - Variables
24 |
25 | private var presenter: MockPresenter?
26 | private var view: ___VARIABLE_productName___ViewController?
27 |
28 | // MARK: Test Functions
29 |
30 | func testPresenter() {
31 | view?.beginAppearanceTransition(true, animated: false)
32 | view?.endAppearanceTransition()
33 | XCTAssertEqual(presenter?.isViewLoaded, true)
34 |
35 | view?.set(title: "___VARIABLE_productName___")
36 | XCTAssertEqual(view?.title, "___VARIABLE_productName___")
37 |
38 | view?.beginAppearanceTransition(false, animated: false)
39 | view?.endAppearanceTransition()
40 | }
41 |
42 | // MARK: Setup
43 |
44 | override func setUp() {
45 | super.setUp()
46 | // Put setup code here. This method is called before the invocation of each test method in the class.
47 |
48 | let presenter = MockPresenter()
49 | self.presenter = presenter
50 |
51 | // FIXME: - Uncomment this section, if you're using a standard VIPER Module
52 | /* ---------------
53 |
54 | view = ___VARIABLE_productName___ViewController(presenter: presenter)
55 |
56 | --------------- */
57 |
58 | // FIXME: - Uncomment this section, if you're using a Storyboard compatible VIPER Module
59 | /* ---------------
60 |
61 | let storyboard: UIStoryboard = UIStoryboard(name: <#T##String#>, bundle: Bundle.main)
62 | view = storyboard.viewController(___VARIABLE_productName___ViewController.self)
63 | view.presenter = presenter
64 |
65 | --------------- */
66 |
67 | guard view == nil else { return }
68 | fatalError("Uncomment one of the Sections Above")
69 | }
70 |
71 | override func tearDown() {
72 | // Put teardown code here. This method is called after the invocation of each test method in the class.
73 | super.tearDown()
74 | }
75 | }
76 |
77 | // MARK: - Mock Classes
78 |
79 | // MARK: -
80 |
81 | private class MockPresenter: ___VARIABLE_productName___ViewPresenterProtocol {
82 |
83 | // MARK: Variables
84 |
85 | var isViewLoaded: Bool = false
86 |
87 | // MARK: Functions
88 |
89 | func viewLoaded() {
90 | isViewLoaded = true
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Templates/VIPER/Module Tests.xctemplate/___FILEBASENAME___PresenterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ___FILENAME___
3 | // Project: ___PROJECTNAME___
4 | //
5 | // Module: ___VARIABLE_productName___
6 | //
7 | // By ___FULLUSERNAME___ ___DATE___
8 | // ___ORGANIZATIONNAME___ ___YEAR___
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import XCTest
14 |
15 | @testable import ___PROJECTNAME___
16 |
17 | import SwiftyVIPER
18 |
19 | // MARK: -
20 |
21 | class ___FILEBASENAMEASIDENTIFIER___: XCTestCase {
22 |
23 | // MARK: - Variables
24 |
25 | private var router: MockRouter?
26 | private var interactor: MockInteractor?
27 | private var view: MockView?
28 |
29 | private var presenter: ___VARIABLE_productName___Presenter?
30 |
31 | // MARK: Test Functions
32 |
33 | func testInteractor() {
34 | presenter?.viewLoaded()
35 | presenter?.viewAppearing()
36 | presenter?.viewAppeared()
37 | presenter?.viewDisappeared()
38 | XCTAssertEqual(interactor?.titleRequested, true)
39 | }
40 |
41 | func testView() {
42 | presenter?.set(title: "___VARIABLE_productName___")
43 | XCTAssertEqual(view?.title, "___VARIABLE_productName___")
44 | }
45 |
46 | // MARK: Setup
47 |
48 | override func setUp() {
49 | super.setUp()
50 | // Put setup code here. This method is called before the invocation of each test method in the class.
51 |
52 | let router = MockRouter()
53 | self.router = router
54 |
55 | let interactor = MockInteractor()
56 | self.interactor = interactor
57 |
58 | presenter = ___VARIABLE_productName___Presenter(router: router, interactor: interactor)
59 |
60 | view = MockView()
61 | presenter?.view = self.view
62 | }
63 |
64 | override func tearDown() {
65 | // Put teardown code here. This method is called after the invocation of each test method in the class.
66 | super.tearDown()
67 | }
68 | }
69 |
70 | // MARK: - Mock Classes
71 |
72 | // MARK: -
73 |
74 | private class MockRouter: RouterProtocol, ___VARIABLE_productName___PresenterRouterProtocol {
75 | // MARK: Variables
76 |
77 | var viewController: UIViewController?
78 | }
79 |
80 | // MARK: -
81 |
82 | private class MockInteractor: ___VARIABLE_productName___PresenterInteractorProtocol {
83 | // MARK: Variables
84 |
85 | var titleRequested: Bool = false
86 |
87 | // MARK: Functions
88 |
89 | func requestTitle() {
90 | titleRequested = true
91 | }
92 | }
93 |
94 | // MARK: -
95 |
96 | private class MockView: ___VARIABLE_productName___PresenterViewProtocol {
97 | // MARK: Variables
98 |
99 | var title: String?
100 |
101 | // MARK: Functions
102 |
103 | func set(title: String?) {
104 | self.title = title
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/RootPresenterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RootPresenterTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Root
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class RootPresenterTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var router: MockRouter?
24 | private var interactor: MockInteractor?
25 | private var view: MockView?
26 | private var presenter: RootPresenter?
27 |
28 | // MARK: Test Functions
29 |
30 | func testInteractor() {
31 | presenter?.viewLoaded()
32 | presenter?.viewAppearing()
33 | presenter?.viewAppeared()
34 | presenter?.viewDisappeared()
35 | XCTAssert(interactor?.titleRequested ?? false)
36 | }
37 |
38 | func testRouter() {
39 | presenter?.detailsSelected()
40 | XCTAssert(router?.shouldShowDetails ?? false)
41 | }
42 |
43 | func testView() {
44 | presenter?.set(title: "Root")
45 | XCTAssertEqual(view?.title, "Root")
46 | }
47 |
48 | // MARK: Setup
49 |
50 | override func setUp() {
51 | super.setUp()
52 | // Put setup code here. This method is called before the invocation of each test method in the class.
53 |
54 | let router = MockRouter()
55 | self.router = router
56 |
57 | let interactor = MockInteractor()
58 | self.interactor = interactor
59 |
60 | view = MockView()
61 |
62 | presenter = RootPresenter(router: router, interactor: interactor)
63 | presenter?.view = self.view
64 | }
65 |
66 | override func tearDown() {
67 | // Put teardown code here. This method is called after the invocation of each test method in the class.
68 | super.tearDown()
69 | }
70 | }
71 |
72 | // MARK: - Mock Classes
73 |
74 | // MARK: -
75 |
76 | private class MockRouter: RouterProtocol, RootPresenterRouterProtocol {
77 |
78 | // MARK: Variables
79 |
80 | var viewController: UIViewController?
81 | var shouldShowDetails: Bool = false
82 |
83 | // MARK: Functions
84 |
85 | func detailsSelected() {
86 | shouldShowDetails = true
87 | }
88 | }
89 |
90 | // MARK: -
91 |
92 | private class MockInteractor: RootPresenterInteractorProtocol {
93 |
94 | // MARK: Variables
95 |
96 | var titleRequested: Bool = false
97 |
98 | // MARK: Functions
99 |
100 | func requestTitle() {
101 | titleRequested = true
102 | }
103 | }
104 |
105 | // MARK: -
106 |
107 | private class MockView: RootPresenterViewProtocol {
108 |
109 | // MARK: Variables
110 |
111 | var title: String?
112 |
113 | // MARK: Functions
114 |
115 | func set(title: String?) {
116 | self.title = title
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExampleTests/DetailPresenterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailPresenterTests.swift
3 | // Project: SwiftyVIPERExample
4 | //
5 | // Module: Detail
6 | //
7 | // By Cody Winton 11/9/16
8 | // codeRed 2016
9 | //
10 |
11 | // MARK: Imports
12 |
13 | import SwiftyVIPER
14 | @testable import SwiftyVIPERExample
15 | import XCTest
16 |
17 | // MARK: -
18 |
19 | class DetailPresenterTests: XCTestCase {
20 |
21 | // MARK: - Variables
22 |
23 | private var router: MockRouter?
24 | private var interactor: MockInteractor?
25 | private var view: MockView?
26 |
27 | private var presenter: DetailPresenter?
28 |
29 | // MARK: Test Functions
30 |
31 | func testInteractor() {
32 | presenter?.viewLoaded()
33 | presenter?.viewAppearing()
34 | presenter?.viewAppeared()
35 | presenter?.viewDisappeared()
36 | XCTAssert(interactor?.titleRequested ?? false)
37 | }
38 |
39 | func testRouter() {
40 | presenter?.closeSelected()
41 | XCTAssert(router?.shouldDismiss ?? false)
42 | }
43 |
44 | func testView() {
45 | presenter?.set(title: "Detail")
46 | XCTAssertEqual(view?.title, "Detail")
47 | }
48 |
49 | // MARK: Setup
50 |
51 | override func setUp() {
52 | super.setUp()
53 | // Put setup code here. This method is called before the invocation of each test method in the class.
54 |
55 | let router = MockRouter()
56 | self.router = router
57 |
58 | let interactor = MockInteractor()
59 | self.interactor = interactor
60 |
61 | view = MockView()
62 |
63 | presenter = DetailPresenter(router: router, interactor: interactor)
64 | presenter?.view = self.view
65 | }
66 |
67 | override func tearDown() {
68 | // Put teardown code here. This method is called after the invocation of each test method in the class.
69 | super.tearDown()
70 | }
71 | }
72 |
73 | // MARK: - Mock Classes
74 |
75 | // MARK: -
76 |
77 | private class MockRouter: RouterProtocol, DetailPresenterRouterProtocol {
78 |
79 | // MARK: Variables
80 |
81 | var viewController: UIViewController?
82 | var shouldDismiss: Bool = false
83 |
84 | // MARK: Functions
85 |
86 | func dismiss(completion: CodeBlock?) {
87 | shouldDismiss = true
88 | completion?()
89 | }
90 | }
91 |
92 | // MARK: -
93 |
94 | private class MockInteractor: DetailPresenterInteractorProtocol {
95 |
96 | // MARK: Variables
97 |
98 | var titleRequested: Bool = false
99 |
100 | // MARK: Functions
101 |
102 | func requestTitle() {
103 | titleRequested = true
104 | }
105 | }
106 |
107 | // MARK: -
108 |
109 | private class MockView: DetailPresenterViewProtocol {
110 |
111 | // MARK: Variables
112 |
113 | var title: String?
114 |
115 | // MARK: Functions
116 |
117 | func set(title: String?) {
118 | self.title = title
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Tests/ProtocolTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ProtocolTests.swift
3 | // SwiftyVIPER
4 | //
5 | // Created by Cody Winton on 11/7/16.
6 | // Copyright © 2016 codeRed. All rights reserved.
7 | //
8 |
9 | // MARK: Imports
10 |
11 | import SwiftyVIPER
12 | import XCTest
13 |
14 | // MARK: -
15 |
16 | class ProtocolTests: XCTestCase {
17 |
18 | // MARK: - Variables
19 |
20 | var module: MockModule?
21 | var router: MockRouter?
22 |
23 | // MARK: Test Functions
24 |
25 | func testPresentDismiss() {
26 |
27 | let viewController = UIViewController()
28 | viewController.beginAppearanceTransition(true, animated: false)
29 | viewController.endAppearanceTransition()
30 |
31 | module?.present(from: viewController, style: UIModalTransitionStyle.crossDissolve, completion: nil)
32 |
33 | router?.dismiss(completion: nil)
34 |
35 | router?.viewController = nil
36 | router?.dismiss(completion: nil)
37 | }
38 |
39 | func testPushPop() {
40 |
41 | let viewController = UIViewController()
42 | let navController = UINavigationController(rootViewController: viewController)
43 | navController.beginAppearanceTransition(true, animated: false)
44 | navController.endAppearanceTransition()
45 |
46 | module?.push(from: navController)
47 | router?.pop()
48 | }
49 |
50 | func testPresent() {
51 |
52 | let viewController = UIViewController()
53 | viewController.beginAppearanceTransition(true, animated: false)
54 | viewController.endAppearanceTransition()
55 |
56 | module?.present(from: viewController, style: UIModalTransitionStyle.crossDissolve, completion: nil)
57 |
58 | let newVC = UIViewController()
59 | newVC.beginAppearanceTransition(true, animated: false)
60 | newVC.endAppearanceTransition()
61 |
62 | router?.present(newVC, completion: nil)
63 |
64 | router?.viewController = nil
65 | router?.present(newVC, completion: nil)
66 | }
67 |
68 | func testPresenter() {
69 |
70 | let presenter = MockPresenter()
71 |
72 | presenter.viewLoaded()
73 | presenter.viewAppearing()
74 | presenter.viewAppeared()
75 | presenter.viewDisappeared()
76 | }
77 |
78 | func testStoryboard() {
79 | let storyboardName: String
80 |
81 | #if os(iOS)
82 | storyboardName = "iOS"
83 | #elseif os(tvOS)
84 | storyboardName = "tvOS"
85 | #else
86 | storyboardName = ""
87 | #endif
88 |
89 | let bundle = Bundle(for: ProtocolTests.self)
90 |
91 | let storyboard = UIStoryboard(name: storyboardName, bundle: bundle)
92 | let viewController = storyboard.viewController(MockViewController.self)
93 | XCTAssertNotNil(viewController)
94 | }
95 |
96 | func testStoryboardIdentifiable() {
97 | XCTAssertFalse(MockViewController.storyboardID.isEmpty)
98 | }
99 |
100 | // MARK: Setup
101 |
102 | override func setUp() {
103 | super.setUp()
104 | // Put setup code here. This method is called before the invocation of each test method in the class.
105 |
106 | module = MockModule()
107 | router = module?.router
108 | }
109 |
110 | override func tearDown() {
111 | // Put teardown code here. This method is called after the invocation of each test method in the class.
112 | super.tearDown()
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | swiftlint_version: 0.24.2
2 |
3 | opt_in_rules:
4 | - array_init
5 | - attributes
6 | - block_based_kvo
7 | - class_delegate_protocol
8 | - closing_brace
9 | - closure_end_indentation
10 | - closure_parameter_position
11 | - closure_spacing
12 | - colon
13 | - comma
14 | - compiler_protocol_init
15 | - contains_over_first_not_nil
16 | - control_statement
17 | - cyclomatic_complexity
18 | - discarded_notification_center_observer
19 | - discouraged_direct_init
20 | - dynamic_inline
21 | - empty_count
22 | - empty_enum_arguments
23 | - empty_parameters
24 | - empty_parentheses_with_trailing_closure
25 | - explicit_init
26 | - explicit_type_interface
27 | - extension_access_modifier
28 | - fatal_error_message
29 | - file_length
30 | - first_where
31 | - for_where
32 | - force_cast
33 | - force_try
34 | - force_unwrapping
35 | - function_body_length
36 | - function_parameter_count
37 | - generic_type_name
38 | - identifier_name
39 | - implicit_getter
40 | - implicit_return
41 | - implicitly_unwrapped_optional
42 | - is_disjoint
43 | - joined_default_parameter
44 | - large_tuple
45 | - leading_whitespace
46 | - legacy_cggeometry_functions
47 | - legacy_constant
48 | - legacy_constructor
49 | - legacy_nsgeometry_functions
50 | - let_var_whitespace
51 | - line_length
52 | - literal_expression_end_indentation
53 | - mark
54 | - multiline_arguments
55 | - multiline_parameters
56 | - multiple_closures_with_trailing_closure
57 | - nesting
58 | - nimble_operator
59 | - no_grouping_extension
60 | - notification_center_detachment
61 | - object_literal
62 | - opening_brace
63 | - operator_usage_whitespace
64 | - operator_whitespace
65 | - overridden_super_call
66 | - override_in_extension
67 | - pattern_matching_keywords
68 | - private_action
69 | - private_outlet
70 | - private_over_fileprivate
71 | - private_unit_test
72 | - prohibited_super_call
73 | - protocol_property_accessors_order
74 | - quick_discouraged_call
75 | - quick_discouraged_focused_test
76 | - quick_discouraged_pending_test
77 | - redundant_discardable_let
78 | - redundant_nil_coalescing
79 | - redundant_optional_initialization
80 | - redundant_void_return
81 | - redundant_string_enum_value
82 | - required_enum_case
83 | - return_arrow_whitespace
84 | - shorthand_operator
85 | - single_test_class
86 | - sorted_first_last
87 | - sorted_imports
88 | - statement_position
89 | - strict_fileprivate
90 | - switch_case_on_newline
91 | - syntactic_sugar
92 | - todo
93 | - trailing_closure
94 | - trailing_comma
95 | - trailing_newline
96 | - trailing_semicolon
97 | - trailing_whitespace
98 | - type_body_length
99 | - type_name
100 | - unused_closure_parameter
101 | - unused_enumerated
102 | - unneeded_parentheses_in_closure_argument
103 | - unused_optional_binding
104 | - valid_ibinspectable
105 | - vertical_parameter_alignment
106 | - vertical_parameter_alignment_on_call
107 | - vertical_whitespace
108 | - void_return
109 | - weak_delegate
110 | - xctfail_message
111 | - yoda_condition
112 |
113 | disabled_rules:
114 | - custom_rules
115 | - conditional_returns_on_newline
116 | - discouraged_object_literal
117 | - explicit_acl
118 | - explicit_enum_raw_value
119 | - explicit_top_level_acl
120 | - file_header
121 | - no_extension_access_modifier
122 | - number_separator
123 | - prefixed_toplevel_constant
124 |
125 | included:
126 | - Sources
127 | - Tests
128 |
129 | excluded:
130 | - Example
131 | - Templates
132 |
133 | private_outlet:
134 | allow_private_set: true
135 |
--------------------------------------------------------------------------------
/Example/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | swiftlint_version: 0.24.2
2 |
3 | opt_in_rules:
4 | - array_init
5 | - attributes
6 | - block_based_kvo
7 | - class_delegate_protocol
8 | - closing_brace
9 | - closure_end_indentation
10 | - closure_parameter_position
11 | - closure_spacing
12 | - colon
13 | - comma
14 | - compiler_protocol_init
15 | - contains_over_first_not_nil
16 | - control_statement
17 | - cyclomatic_complexity
18 | - discarded_notification_center_observer
19 | - discouraged_direct_init
20 | - dynamic_inline
21 | - empty_count
22 | - empty_enum_arguments
23 | - empty_parameters
24 | - empty_parentheses_with_trailing_closure
25 | - explicit_init
26 | - explicit_type_interface
27 | - extension_access_modifier
28 | - fatal_error_message
29 | - file_length
30 | - first_where
31 | - for_where
32 | - force_cast
33 | - force_try
34 | - force_unwrapping
35 | - function_body_length
36 | - function_parameter_count
37 | - generic_type_name
38 | - identifier_name
39 | - implicit_getter
40 | - implicit_return
41 | - implicitly_unwrapped_optional
42 | - is_disjoint
43 | - joined_default_parameter
44 | - large_tuple
45 | - leading_whitespace
46 | - legacy_cggeometry_functions
47 | - legacy_constant
48 | - legacy_constructor
49 | - legacy_nsgeometry_functions
50 | - let_var_whitespace
51 | - line_length
52 | - literal_expression_end_indentation
53 | - mark
54 | - multiline_arguments
55 | - multiline_parameters
56 | - multiple_closures_with_trailing_closure
57 | - nesting
58 | - nimble_operator
59 | - no_grouping_extension
60 | - notification_center_detachment
61 | - object_literal
62 | - opening_brace
63 | - operator_usage_whitespace
64 | - operator_whitespace
65 | - overridden_super_call
66 | - override_in_extension
67 | - pattern_matching_keywords
68 | - private_action
69 | - private_outlet
70 | - private_over_fileprivate
71 | - private_unit_test
72 | - prohibited_super_call
73 | - protocol_property_accessors_order
74 | - quick_discouraged_call
75 | - quick_discouraged_focused_test
76 | - quick_discouraged_pending_test
77 | - redundant_discardable_let
78 | - redundant_nil_coalescing
79 | - redundant_optional_initialization
80 | - redundant_void_return
81 | - redundant_string_enum_value
82 | - required_enum_case
83 | - return_arrow_whitespace
84 | - shorthand_operator
85 | - single_test_class
86 | - sorted_first_last
87 | - sorted_imports
88 | - statement_position
89 | - strict_fileprivate
90 | - switch_case_on_newline
91 | - syntactic_sugar
92 | - todo
93 | - trailing_closure
94 | - trailing_comma
95 | - trailing_newline
96 | - trailing_semicolon
97 | - trailing_whitespace
98 | - type_body_length
99 | - type_name
100 | - unused_closure_parameter
101 | - unused_enumerated
102 | - unneeded_parentheses_in_closure_argument
103 | - unused_optional_binding
104 | - valid_ibinspectable
105 | - vertical_parameter_alignment
106 | - vertical_parameter_alignment_on_call
107 | - vertical_whitespace
108 | - void_return
109 | - weak_delegate
110 | - xctfail_message
111 | - yoda_condition
112 |
113 | disabled_rules:
114 | - custom_rules
115 | - conditional_returns_on_newline
116 | - discouraged_object_literal
117 | - explicit_acl
118 | - explicit_enum_raw_value
119 | - explicit_top_level_acl
120 | - file_header
121 | - no_extension_access_modifier
122 | - number_separator
123 | - prefixed_toplevel_constant
124 |
125 | included:
126 | - SwiftyVIPERExample
127 | - SwiftyVIPERExampleTests
128 |
129 | excluded:
130 | - Pods
131 | - Carthage
132 |
133 | private_outlet:
134 | allow_private_set: true
135 |
--------------------------------------------------------------------------------
/SwiftyVIPER.xcodeproj/xcshareddata/xcschemes/SwiftyVIPERiOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
35 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
54 |
55 |
56 |
67 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
86 |
92 |
93 |
94 |
95 |
97 |
98 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/SwiftyVIPER.xcodeproj/xcshareddata/xcschemes/SwiftyVIPERtvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
35 |
41 |
42 |
43 |
44 |
45 |
51 |
52 |
53 |
54 |
55 |
56 |
67 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
86 |
92 |
93 |
94 |
95 |
97 |
98 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | `SwiftyVIPER` adheres to [Semantic Versioning](http://semver.org/).
5 | All changes are ordered: Added, Updated, Removed, Fixed
6 |
7 | ---
8 |
9 | ## [2.0](https://github.com/codytwinton/SwiftyVIPER/releases/tag/2.0)
10 |
11 | ### Updated for Swift 4
12 |
13 | Released on 2018-02-04
14 |
15 | #### Updated
16 |
17 | - Changed all templates and source code to support Swift 4.0
18 | - Updated by [Cody Winton](https://github.com/codytwinton)
19 | - Changed all templates and source code to support Swiftlint 0.24.2
20 | - Updated by [Cody Winton](https://github.com/codytwinton)
21 |
22 | ---
23 |
24 | ## [1.2.3](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.2.3)
25 |
26 | ### Added SwiftLint
27 |
28 | Released on 2017-01-06
29 |
30 | #### Updated
31 |
32 | - Implemented [SwiftLint](https://github.com/realm/SwiftLint) for the entire project
33 | - Updated by [Cody Winton](https://github.com/codytwinton)
34 |
35 | ---
36 |
37 | ## [1.2.2](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.2.2)
38 |
39 | ### Improved VIPER Templates
40 |
41 | Released on 2016-12-24
42 |
43 | #### Updated
44 |
45 | - Changed template Interactor from `struct` to `class`
46 | - Updated by [Cody Winton](https://github.com/codytwinton)
47 |
48 | ---
49 |
50 | ## [1.2.1](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.2.1)
51 |
52 | ### Improved VIPER Templates
53 |
54 | Released on 2016-12-18
55 |
56 | #### Added
57 |
58 | - Added `final` to certain template classes
59 | - Added by [Cody Winton](https://github.com/codytwinton)
60 |
61 | #### Updated
62 |
63 | - Changed all template classes from `NSObject` subclasses to a plain Swift `class`
64 | - Updated by [Cody Winton](https://github.com/codytwinton)
65 | - Changed template Interactor from `class` to `struct`
66 | - Updated by [Cody Winton](https://github.com/codytwinton)
67 |
68 | #### Fixed
69 |
70 | - Removed old `ViewPresenterProtocol` functions from Templates
71 | - Fixed by [Cody Winton](https://github.com/codytwinton)
72 |
73 | ---
74 |
75 | ## [1.2.0](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.2.0)
76 |
77 | ### Improved Presenter Interaction
78 |
79 | Released on 2016-12-01
80 |
81 | #### Updated
82 |
83 | - `viewLoaded()` no longer optional for Presenters conforming to `ViewPresenterProtocol`
84 | - Updated by [Cody Winton](https://github.com/codytwinton)
85 | - `CompletionBlock` was renamed `CodeBlock`
86 | - Updated by [Cody Winton](https://github.com/codytwinton)
87 |
88 | #### Removed
89 |
90 | - `ViewPresenterProtocol.viewAppearing()`
91 | - Removed by [Cody Winton](https://github.com/codytwinton)
92 | - `ViewPresenterProtocol.viewAppeared()`
93 | - Removed by [Cody Winton](https://github.com/codytwinton)
94 | - `ViewPresenterProtocol.viewDisappeared()`
95 | - Removed by [Cody Winton](https://github.com/codytwinton)
96 |
97 | ---
98 |
99 | ## [1.1](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.1)
100 |
101 | ### Improved Storyboard Interaction
102 |
103 | Released on 2016-11-29
104 |
105 | #### Added
106 |
107 | - `StoryboardIdentifiable` extension to enable default `storyboardID` value for a `UIViewController`
108 | - Added by [Cody Winton](https://github.com/codytwinton)
109 |
110 | #### Updated
111 |
112 | - The protocol `ViewStoryboardProtocol` was renamed `StoryboardIdentifiable`
113 | - Updated by [Cody Winton](https://github.com/codytwinton)
114 |
115 | ---
116 |
117 | ## [1.0.1](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.0.1)
118 |
119 | ### Minor Podspec Update
120 |
121 | Released on 2016-11-21
122 |
123 | #### Fixed
124 |
125 | - Officially requires automatic reference counting
126 | - Fixed by [Cody Winton](https://github.com/codytwinton)
127 |
128 | ---
129 |
130 | ## [1.0](https://github.com/codytwinton/SwiftyVIPER/releases/tag/1.0)
131 |
132 | ### Official Release
133 |
134 | Released on 2016-11-16
135 |
136 | #### Added
137 |
138 | - iOS & tvOS Support
139 | - Fixed by [Cody Winton](https://github.com/codytwinton)
140 | - Cocoapods, Carthage, and Manual Support
141 | - Fixed by [Cody Winton](https://github.com/codytwinton)
142 |
143 | #### Updated
144 |
145 | - Improved VIPER Templates
146 | - Fixed by [Cody Winton](https://github.com/codytwinton)
147 |
--------------------------------------------------------------------------------
/Sources/Protocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Protocols.swift
3 | // SwiftyVIPER
4 | //
5 | // Created by Cody Winton on 9/21/16.
6 | // Copyright © 2016 codeRed. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// A block of code
12 | public typealias CodeBlock = () -> Void
13 |
14 | /// A block of code
15 | @available(*, deprecated, message: "Deprecated in SwiftyVIPER version 1.2. Use CodeBlock instead", renamed: "CodeBlock")
16 | public typealias CompletionBlock = CodeBlock
17 |
18 | // MARK: Protocols
19 |
20 | /** This Protocol gives some basic functionality to a Module
21 |
22 | - note: This Protocol should be conformed to by a Module object
23 | - note: A module should contain:
24 | - `view` the view object, normally a view controller
25 | - `presenter` the presenter object
26 | - `router` the router object
27 | - `interactor` the interactor object
28 | */
29 | public protocol ModuleProtocol: class {
30 | /** The View Controller owned by the Module
31 | - important: Should be a strong reference
32 | */
33 | var viewController: UIViewController { get }
34 |
35 | /** Presents the View Controller owned by the Module
36 | - parameter fromVC: The view controller to present the module from
37 | - parameter style: The modal transition style to use
38 | - parameter completion: The code block to call when the transition completes
39 | */
40 | func present(from fromVC: UIViewController?, style: UIModalTransitionStyle, completion: CodeBlock?)
41 |
42 | /** Pushes the View Controller owned by the Module
43 | - parameter navController: The navigation controller to push the module on
44 | */
45 | func push(from navController: UINavigationController?)
46 | }
47 |
48 | /** This Protocol gives some basic functionality to a Router
49 | - note: This Protocol should be conformed to by a Router object
50 | */
51 | public protocol RouterProtocol: class {
52 | /** The View Controller referenced by the Router
53 | - important: Should be a weak reference
54 | */
55 | var viewController: UIViewController? { get }
56 | }
57 |
58 | /** This Protocol gives some basic functionality to a Router that can be called by a Presenter
59 | - note: This Protocol should be conformed to by new Presenter to Router Protocol
60 | - note: The Presenter to Router protocol should be conformed to by a Router and referenced by the Presenter
61 | */
62 | public protocol PresenterRouterProtocol: class {
63 | /** Presents a view object from a Presenter
64 | - note: This should be used to present a simple view controller, like a `UIAlertController`.
65 | - note: A new module should be initialized and presented directly from the Router object, not a Presenter
66 | - parameter view: The view controller to present
67 | - parameter completion: The code block to call when the transition completes
68 | */
69 | func present(_ view: UIViewController, completion: CodeBlock?)
70 |
71 | /** Dismisses a Module that was presented modally
72 | - parameter completion: The code block to call when the transition completes
73 | */
74 | func dismiss(completion: CodeBlock?)
75 |
76 | /** Pops a Module that was pushed
77 | - returns: Should return the view controller that was popped
78 | */
79 | @discardableResult
80 | func pop() -> UIViewController?
81 | }
82 |
83 | /** This Protocol gives some basic functionality to a Presenter that can be called by a View
84 | - note: This Protocol should be conformed to by new View to Presenter Protocol
85 | - note: The View to Presenter protocol should be conformed to by a Presenter and referenced by the View
86 | */
87 | public protocol ViewPresenterProtocol {
88 | /// Call when the View is loaded
89 | func viewLoaded()
90 | /** Call when the View is appearing
91 | - note: Deprecated to reduce the number of calls to the Presenter
92 | */
93 | @available(*, deprecated, message: "Deprecated in SwiftyVIPER version 1.2")
94 | func viewAppearing()
95 | /** Call when the View has appeared
96 | - note: Deprecated to reduce the number of calls to the Presenter
97 | */
98 | @available(*, deprecated, message: "Deprecated in SwiftyVIPER version 1.2")
99 | func viewAppeared()
100 | /** Call when the View has disappeared
101 | - note: Deprecated to reduce the number of calls to the Presenter
102 | */
103 | @available(*, deprecated, message: "Deprecated in SwiftyVIPER version 1.2")
104 | func viewDisappeared()
105 | }
106 |
107 | /** This Protocol is conformed to by an object and used to initialize via. Storyboard
108 | */
109 | public protocol StoryboardIdentifiable: class {
110 | /// The Storyboard ID to use for a View Controller
111 | static var storyboardID: String { get }
112 | }
113 |
114 | /** This Protocol is used to initialize a View Controller via. Storyboard
115 | */
116 | @available(*, deprecated,
117 | message: "Deprecated in SwiftyVIPER version 1.1. Use StoryboardIdentifiable instead",
118 | renamed: "StoryboardIdentifiable")
119 | public typealias ViewStoryboardProtocol = StoryboardIdentifiable
120 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample/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 |
33 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftyVIPER
2 |
3 | ![Header][main-image]
4 |
5 | ---
6 |
7 | [![Language][lang-image]](https://swift.org/)
8 | [![License][license-image]](LICENSE)
9 | [![Platform][platform-image]](http://cocoapods.org/pods/SwiftyVIPER)
10 |
11 | [![Build Status][build-image]](https://travis-ci.org/codytwinton/SwiftyVIPER)
12 | [![Docs Percentage][docs-image]](http://cocoadocs.org/docsets/SwiftyVIPER)
13 | [![Code Coverage][codecov-image]](https://codecov.io/gh/codytwinton/SwiftyVIPER)
14 | [![Code Beat][codebeat-image]](https://codebeat.co/projects/github-com-codytwinton-swiftyviper)
15 |
16 | [![Pod Version][pod-version-image]](http://cocoapods.org/pods/SwiftyVIPER)
17 | [![Carthage Compatible][carthage-image]](https://github.com/Carthage/Carthage)
18 |
19 | SwiftyVIPER allows easy use of VIPER architecture throughout your iOS application.
20 |
21 | ## VIPER Architecture
22 |
23 | What is VIPER? Great question! VIPER is a [backronym](https://en.wikipedia.org/wiki/Backronym) which stands for:
24 |
25 | * View
26 | * Interactor
27 | * Presenter
28 | * Entity
29 | * Router
30 |
31 | If all of this is totally new for you, check out my running list of [VIPER Resources](#resources)
32 |
33 | ## Features
34 |
35 | * [x] VIPER Module Templates
36 | * [x] VIPER Unit Test Templates
37 | * [x] Simple Module Initialization and Presentation
38 | * [x] CocoaPods Support
39 | * [x] Carthage Support
40 |
41 | ## Requirements
42 |
43 | * iOS 8.0+ | tvOS 9.0+
44 | * Xcode 9
45 | * Swift 4
46 |
47 | ## Installation
48 |
49 | ### CocoaPods
50 |
51 | You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyVIPER` by adding it to your `Podfile`:
52 |
53 | ```ruby
54 | source 'https://github.com/CocoaPods/Specs.git'
55 | use_frameworks!
56 | platform :ios, '8.0'
57 |
58 | def shared_pods
59 | pod 'SwiftyVIPER', '~> 1.0'
60 | end
61 |
62 | target 'MyApp' do
63 | shared_pods
64 | end
65 |
66 | target 'MyAppTests' do
67 | shared_pods
68 | end
69 | ```
70 |
71 | To get the full benefits import `SwiftyVIPER` wherever you import UIKit
72 |
73 | ``` swift
74 | import UIKit
75 | import SwiftyVIPER
76 | ```
77 |
78 | ### Carthage
79 |
80 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
81 |
82 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
83 |
84 | ```bash
85 | brew update
86 | brew install carthage
87 | ```
88 |
89 | To integrate SwiftyVIPER into your Xcode project using Carthage, specify it in your `Cartfile`:
90 |
91 | ```ogdl
92 | github "codytwinton/SwiftyVIPER" ~> 1.0
93 | ```
94 |
95 | Run `carthage update` to build the framework and drag the built `SwiftyVIPER.framework` into your Xcode project.
96 |
97 | #### Manually
98 |
99 | This is discouraged, but allowed. :D
100 |
101 | 1. Download and drop the ```Source``` folder in your project.
102 | 2. Congratulations!
103 |
104 | ---
105 |
106 | ## Usage of SwiftyVIPER
107 |
108 | ### Installing Templates
109 |
110 | If you're looking for VIPER architecture templates to use directly within Xcode, you can find these in the `/Templates/VIPER` folder. Open your terminal and run:
111 |
112 | ```bash
113 | cd PATH/TO/REPO
114 | ```
115 |
116 | Then, simply run this command in your terminal:
117 |
118 | ```bash
119 | mkdir -p ~/Library/Developer/Xcode/Templates/File\ Templates
120 | cp -R Templates/VIPER ~/Library/Developer/Xcode/Templates/File\ Templates
121 | ```
122 |
123 | ### Adding a Module
124 |
125 | Once you've installed the VIPER Templates, you're ready to add a module. Select `File > New > File` or use press `⌘N` to bring up the template selector. You'll find the templates at the bottom.
126 |
127 | Choose `Module` for a normal module, `Module Storyboard` for a normal module that interacts with Storyboards, or `Module Tests` for a module unit tests template.
128 |
129 | 
130 |
131 | Next, choose the Module name. We'll go with `Custom`.
132 |
133 | 
134 |
135 | This will create 5 files per module:
136 |
137 | * `CustomModule.swift`
138 | * `CustomViewController.swift`
139 | * `CustomPresenter.swift`
140 | * `CustomRouter.swift`
141 | * `CustomInteractor.swift`
142 |
143 | Don't forget to target your main app. Once you've added the main template, go ahead and add the Unit Test template. **Make sure it's the same name!** In this case, we'd stay with `Custom`.
144 |
145 | ### Using SwiftyVIPER
146 |
147 | Simply add a new module using the VIPER template. Once done, simply call:
148 |
149 | ```swift
150 | import SwiftyVIPER
151 |
152 | CustomModule().present(from: self.viewController, style: .coverVertical, completion: nil)
153 | ```
154 |
155 | The module will handle the rest, including initializing and attaching all the connections necessary for the Module to show properly.
156 |
157 | ## Contribute
158 |
159 | We would love for you to contribute to **SwiftyVIPER**, check the ``LICENSE`` file for more info. Pull Requests welcome!
160 |
161 | ## Resources
162 |
163 | * [mutualmobile.com](https://mutualmobile.com/posts/meet-viper-fast-agile-non-lethal-ios-architecture-framework)
164 | * [objc.io](https://www.objc.io/issues/13-architecture/viper/)
165 | * [ckl.io](https://www.ckl.io/blog/ios-project-architecture-using-viper/)
166 | * [stackoverflow.com](http://stackoverflow.com/questions/35132664/why-protocols-are-used-in-both-direction-in-viper-architecture-rather-than-in-on)
167 | * [yalantis.com](https://yalantis.com/blog/tree-of-models-as-an-alternative-app-architecture-model/)
168 | * [medium.com](https://medium.com/mobile-travel-technologies/architecting-mobile-apps-with-b-viper-modules-e94e277c8d68)
169 | * [speakerdeck.com](https://speakerdeck.com/sergigracia/clean-architecture-viper)
170 | * [brigade.engineering](https://brigade.engineering/brigades-experience-using-an-mvc-alternative-36ef1601a41f#.tezoetq87)
171 |
172 | ## Meta
173 |
174 | * Cody Winton – [@codytwinton](https://twitter.com/codytwinton)
175 | * Distributed under the MIT license. See [LICENSE][license-url] for more information.
176 | * Inspired by [ViperMcFlurry](https://github.com/rambler-digital-solutions/ViperMcFlurry)
177 | * README edited with [StackEdit](https://stackedit.io/)
178 |
179 | [main-image]: Assets/SwiftyVIPER.png
180 | [build-image]: https://travis-ci.org/codytwinton/SwiftyVIPER.svg?branch=master
181 | [carthage-image]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg
182 | [codebeat-image]: https://codebeat.co/badges/74c04e5b-e6a2-4baa-9e09-5b08d87dcabc
183 | [codecov-image]: https://codecov.io/gh/codytwinton/SwiftyVIPER/branch/master/graph/badge.svg
184 | [docs-image]: https://img.shields.io/cocoapods/metrics/doc-percent/SwiftyVIPER.svg
185 | [lang-image]: https://img.shields.io/badge/swift-4.0-orange.svg
186 | [license-image]: https://img.shields.io/github/license/codytwinton/SwiftyVIPER.svg
187 | [platform-image]: https://img.shields.io/cocoapods/p/SwiftyVIPER.svg
188 | [pod-version-image]: https://img.shields.io/cocoapods/v/SwiftyVIPER.svg
189 |
--------------------------------------------------------------------------------
/SwiftyVIPER.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6A3037CE1DDCE1160016B3E9 /* SwiftyVIPER.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AF4DD0F1DDCCBF000C49188 /* SwiftyVIPER.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | 6A3037CF1DDCE1200016B3E9 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ACF463B1DD1454500A49396 /* Protocols.swift */; };
12 | 6A3037D01DDCE1270016B3E9 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9431DD2A54E0092B050 /* Extensions.swift */; };
13 | 6A3037DA1DDCE2160016B3E9 /* SwiftyVIPER.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A3037C51DDCDE2C0016B3E9 /* SwiftyVIPER.framework */; };
14 | 6A3037E11DDCE2DD0016B3E9 /* ProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ACF466F1DD1495000A49396 /* ProtocolTests.swift */; };
15 | 6A3037E21DDCE2DD0016B3E9 /* MockModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AF9E0F01DDC055D00F81BEA /* MockModule.swift */; };
16 | 6A3037E41DDCE3130016B3E9 /* tvOS.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6A3037E31DDCE3130016B3E9 /* tvOS.storyboard */; };
17 | 6AF0EB401DDCD8EE00F9506F /* SwiftyVIPER.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AF4DD0F1DDCCBF000C49188 /* SwiftyVIPER.h */; settings = {ATTRIBUTES = (Public, ); }; };
18 | 6AF0EB411DDCD8F300F9506F /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ACF463B1DD1454500A49396 /* Protocols.swift */; };
19 | 6AF0EB421DDCD8F300F9506F /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9431DD2A54E0092B050 /* Extensions.swift */; };
20 | 6AF0EB4F1DDCD94100F9506F /* SwiftyVIPER.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6AF0EB291DDCD5A300F9506F /* SwiftyVIPER.framework */; };
21 | 6AF0EB551DDCD98100F9506F /* iOS.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AF4DD0D1DDCCB9B00C49188 /* iOS.storyboard */; };
22 | 6AF0EB561DDCD98100F9506F /* ProtocolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ACF466F1DD1495000A49396 /* ProtocolTests.swift */; };
23 | 6AF0EB571DDCD98100F9506F /* MockModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AF9E0F01DDC055D00F81BEA /* MockModule.swift */; };
24 | /* End PBXBuildFile section */
25 |
26 | /* Begin PBXContainerItemProxy section */
27 | 6A3037DB1DDCE2160016B3E9 /* PBXContainerItemProxy */ = {
28 | isa = PBXContainerItemProxy;
29 | containerPortal = 6A2D6F691DD144A4008BA1C6 /* Project object */;
30 | proxyType = 1;
31 | remoteGlobalIDString = 6A3037C41DDCDE2C0016B3E9;
32 | remoteInfo = SwiftyVIPERtvOS;
33 | };
34 | 6AF0EB501DDCD94100F9506F /* PBXContainerItemProxy */ = {
35 | isa = PBXContainerItemProxy;
36 | containerPortal = 6A2D6F691DD144A4008BA1C6 /* Project object */;
37 | proxyType = 1;
38 | remoteGlobalIDString = 6AF0EB281DDCD5A300F9506F;
39 | remoteInfo = SwiftyVIPERiOS;
40 | };
41 | /* End PBXContainerItemProxy section */
42 |
43 | /* Begin PBXFileReference section */
44 | 6A24A9431DD2A54E0092B050 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; };
45 | 6A3037C51DDCDE2C0016B3E9 /* SwiftyVIPER.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyVIPER.framework; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 6A3037D51DDCE2160016B3E9 /* SwiftyVIPERtvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyVIPERtvOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
47 | 6A3037E31DDCE3130016B3E9 /* tvOS.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = tvOS.storyboard; sourceTree = ""; };
48 | 6ACF463B1DD1454500A49396 /* Protocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Protocols.swift; sourceTree = ""; };
49 | 6ACF466F1DD1495000A49396 /* ProtocolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProtocolTests.swift; sourceTree = ""; };
50 | 6AF0EB291DDCD5A300F9506F /* SwiftyVIPER.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyVIPER.framework; sourceTree = BUILT_PRODUCTS_DIR; };
51 | 6AF0EB4A1DDCD94100F9506F /* SwiftyVIPERiOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyVIPERiOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
52 | 6AF4DD0D1DDCCB9B00C49188 /* iOS.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = iOS.storyboard; sourceTree = ""; };
53 | 6AF4DD0F1DDCCBF000C49188 /* SwiftyVIPER.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SwiftyVIPER.h; sourceTree = ""; };
54 | 6AF4DD101DDCCBF000C49188 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
55 | 6AF4DD141DDCCC3700C49188 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
56 | 6AF9E0F01DDC055D00F81BEA /* MockModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockModule.swift; sourceTree = ""; };
57 | /* End PBXFileReference section */
58 |
59 | /* Begin PBXFrameworksBuildPhase section */
60 | 6A3037C11DDCDE2C0016B3E9 /* Frameworks */ = {
61 | isa = PBXFrameworksBuildPhase;
62 | buildActionMask = 2147483647;
63 | files = (
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | 6A3037D21DDCE2160016B3E9 /* Frameworks */ = {
68 | isa = PBXFrameworksBuildPhase;
69 | buildActionMask = 2147483647;
70 | files = (
71 | 6A3037DA1DDCE2160016B3E9 /* SwiftyVIPER.framework in Frameworks */,
72 | );
73 | runOnlyForDeploymentPostprocessing = 0;
74 | };
75 | 6AF0EB251DDCD5A300F9506F /* Frameworks */ = {
76 | isa = PBXFrameworksBuildPhase;
77 | buildActionMask = 2147483647;
78 | files = (
79 | );
80 | runOnlyForDeploymentPostprocessing = 0;
81 | };
82 | 6AF0EB471DDCD94100F9506F /* Frameworks */ = {
83 | isa = PBXFrameworksBuildPhase;
84 | buildActionMask = 2147483647;
85 | files = (
86 | 6AF0EB4F1DDCD94100F9506F /* SwiftyVIPER.framework in Frameworks */,
87 | );
88 | runOnlyForDeploymentPostprocessing = 0;
89 | };
90 | /* End PBXFrameworksBuildPhase section */
91 |
92 | /* Begin PBXGroup section */
93 | 6A2D6F681DD144A4008BA1C6 = {
94 | isa = PBXGroup;
95 | children = (
96 | 6ACF463A1DD1454500A49396 /* Sources */,
97 | 6A2D6F881DD144A5008BA1C6 /* Tests */,
98 | 6A2D6F721DD144A4008BA1C6 /* Products */,
99 | );
100 | sourceTree = "";
101 | };
102 | 6A2D6F721DD144A4008BA1C6 /* Products */ = {
103 | isa = PBXGroup;
104 | children = (
105 | 6AF0EB291DDCD5A300F9506F /* SwiftyVIPER.framework */,
106 | 6AF0EB4A1DDCD94100F9506F /* SwiftyVIPERiOSTests.xctest */,
107 | 6A3037C51DDCDE2C0016B3E9 /* SwiftyVIPER.framework */,
108 | 6A3037D51DDCE2160016B3E9 /* SwiftyVIPERtvOSTests.xctest */,
109 | );
110 | name = Products;
111 | sourceTree = "";
112 | };
113 | 6A2D6F881DD144A5008BA1C6 /* Tests */ = {
114 | isa = PBXGroup;
115 | children = (
116 | 6A3037E51DDCE3CA0016B3E9 /* Storyboards */,
117 | 6AF4DD141DDCCC3700C49188 /* Info.plist */,
118 | 6ACF466F1DD1495000A49396 /* ProtocolTests.swift */,
119 | 6AF9E0F01DDC055D00F81BEA /* MockModule.swift */,
120 | );
121 | path = Tests;
122 | sourceTree = "";
123 | };
124 | 6A3037E51DDCE3CA0016B3E9 /* Storyboards */ = {
125 | isa = PBXGroup;
126 | children = (
127 | 6AF4DD0D1DDCCB9B00C49188 /* iOS.storyboard */,
128 | 6A3037E31DDCE3130016B3E9 /* tvOS.storyboard */,
129 | );
130 | name = Storyboards;
131 | sourceTree = "";
132 | };
133 | 6ACF463A1DD1454500A49396 /* Sources */ = {
134 | isa = PBXGroup;
135 | children = (
136 | 6AF4DD0F1DDCCBF000C49188 /* SwiftyVIPER.h */,
137 | 6AF4DD101DDCCBF000C49188 /* Info.plist */,
138 | 6ACF463B1DD1454500A49396 /* Protocols.swift */,
139 | 6A24A9431DD2A54E0092B050 /* Extensions.swift */,
140 | );
141 | path = Sources;
142 | sourceTree = "";
143 | };
144 | /* End PBXGroup section */
145 |
146 | /* Begin PBXHeadersBuildPhase section */
147 | 6A3037C21DDCDE2C0016B3E9 /* Headers */ = {
148 | isa = PBXHeadersBuildPhase;
149 | buildActionMask = 2147483647;
150 | files = (
151 | 6A3037CE1DDCE1160016B3E9 /* SwiftyVIPER.h in Headers */,
152 | );
153 | runOnlyForDeploymentPostprocessing = 0;
154 | };
155 | 6AF0EB261DDCD5A300F9506F /* Headers */ = {
156 | isa = PBXHeadersBuildPhase;
157 | buildActionMask = 2147483647;
158 | files = (
159 | 6AF0EB401DDCD8EE00F9506F /* SwiftyVIPER.h in Headers */,
160 | );
161 | runOnlyForDeploymentPostprocessing = 0;
162 | };
163 | /* End PBXHeadersBuildPhase section */
164 |
165 | /* Begin PBXNativeTarget section */
166 | 6A3037C41DDCDE2C0016B3E9 /* SwiftyVIPERtvOS */ = {
167 | isa = PBXNativeTarget;
168 | buildConfigurationList = 6A3037CC1DDCDE2C0016B3E9 /* Build configuration list for PBXNativeTarget "SwiftyVIPERtvOS" */;
169 | buildPhases = (
170 | 6A3037C01DDCDE2C0016B3E9 /* Sources */,
171 | 6AA354C81E1783A500FB46AA /* Swift Lint */,
172 | 6A3037C11DDCDE2C0016B3E9 /* Frameworks */,
173 | 6A3037C21DDCDE2C0016B3E9 /* Headers */,
174 | 6A3037C31DDCDE2C0016B3E9 /* Resources */,
175 | );
176 | buildRules = (
177 | );
178 | dependencies = (
179 | );
180 | name = SwiftyVIPERtvOS;
181 | productName = SwiftyVIPER;
182 | productReference = 6A3037C51DDCDE2C0016B3E9 /* SwiftyVIPER.framework */;
183 | productType = "com.apple.product-type.framework";
184 | };
185 | 6A3037D41DDCE2160016B3E9 /* SwiftyVIPERtvOSTests */ = {
186 | isa = PBXNativeTarget;
187 | buildConfigurationList = 6A3037DD1DDCE2160016B3E9 /* Build configuration list for PBXNativeTarget "SwiftyVIPERtvOSTests" */;
188 | buildPhases = (
189 | 6A3037D11DDCE2160016B3E9 /* Sources */,
190 | 6A3037D21DDCE2160016B3E9 /* Frameworks */,
191 | 6A3037D31DDCE2160016B3E9 /* Resources */,
192 | );
193 | buildRules = (
194 | );
195 | dependencies = (
196 | 6A3037DC1DDCE2160016B3E9 /* PBXTargetDependency */,
197 | );
198 | name = SwiftyVIPERtvOSTests;
199 | productName = SwiftyVIPERtvOSTests;
200 | productReference = 6A3037D51DDCE2160016B3E9 /* SwiftyVIPERtvOSTests.xctest */;
201 | productType = "com.apple.product-type.bundle.unit-test";
202 | };
203 | 6AF0EB281DDCD5A300F9506F /* SwiftyVIPERiOS */ = {
204 | isa = PBXNativeTarget;
205 | buildConfigurationList = 6AF0EB3A1DDCD5A300F9506F /* Build configuration list for PBXNativeTarget "SwiftyVIPERiOS" */;
206 | buildPhases = (
207 | 6AF0EB241DDCD5A300F9506F /* Sources */,
208 | 6AA354C71E17838F00FB46AA /* Swift Lint */,
209 | 6AF0EB251DDCD5A300F9506F /* Frameworks */,
210 | 6AF0EB261DDCD5A300F9506F /* Headers */,
211 | 6AF0EB271DDCD5A300F9506F /* Resources */,
212 | );
213 | buildRules = (
214 | );
215 | dependencies = (
216 | );
217 | name = SwiftyVIPERiOS;
218 | productName = SwiftyVIPER;
219 | productReference = 6AF0EB291DDCD5A300F9506F /* SwiftyVIPER.framework */;
220 | productType = "com.apple.product-type.framework";
221 | };
222 | 6AF0EB491DDCD94100F9506F /* SwiftyVIPERiOSTests */ = {
223 | isa = PBXNativeTarget;
224 | buildConfigurationList = 6AF0EB521DDCD94100F9506F /* Build configuration list for PBXNativeTarget "SwiftyVIPERiOSTests" */;
225 | buildPhases = (
226 | 6AF0EB461DDCD94100F9506F /* Sources */,
227 | 6AF0EB471DDCD94100F9506F /* Frameworks */,
228 | 6AF0EB481DDCD94100F9506F /* Resources */,
229 | );
230 | buildRules = (
231 | );
232 | dependencies = (
233 | 6AF0EB511DDCD94100F9506F /* PBXTargetDependency */,
234 | );
235 | name = SwiftyVIPERiOSTests;
236 | productName = SwiftyVIPERiOSTests;
237 | productReference = 6AF0EB4A1DDCD94100F9506F /* SwiftyVIPERiOSTests.xctest */;
238 | productType = "com.apple.product-type.bundle.unit-test";
239 | };
240 | /* End PBXNativeTarget section */
241 |
242 | /* Begin PBXProject section */
243 | 6A2D6F691DD144A4008BA1C6 /* Project object */ = {
244 | isa = PBXProject;
245 | attributes = {
246 | LastSwiftUpdateCheck = 0810;
247 | LastUpgradeCheck = 0910;
248 | ORGANIZATIONNAME = SwiftyVIPER;
249 | TargetAttributes = {
250 | 6A3037C41DDCDE2C0016B3E9 = {
251 | CreatedOnToolsVersion = 8.1;
252 | DevelopmentTeam = FUC97LYJ62;
253 | LastSwiftMigration = 0910;
254 | ProvisioningStyle = Automatic;
255 | };
256 | 6A3037D41DDCE2160016B3E9 = {
257 | CreatedOnToolsVersion = 8.1;
258 | DevelopmentTeam = FUC97LYJ62;
259 | LastSwiftMigration = 0910;
260 | ProvisioningStyle = Automatic;
261 | };
262 | 6AF0EB281DDCD5A300F9506F = {
263 | CreatedOnToolsVersion = 8.1;
264 | DevelopmentTeam = FUC97LYJ62;
265 | LastSwiftMigration = 0910;
266 | ProvisioningStyle = Automatic;
267 | };
268 | 6AF0EB491DDCD94100F9506F = {
269 | CreatedOnToolsVersion = 8.1;
270 | DevelopmentTeam = FUC97LYJ62;
271 | LastSwiftMigration = 0910;
272 | ProvisioningStyle = Automatic;
273 | };
274 | };
275 | };
276 | buildConfigurationList = 6A2D6F6C1DD144A4008BA1C6 /* Build configuration list for PBXProject "SwiftyVIPER" */;
277 | compatibilityVersion = "Xcode 3.2";
278 | developmentRegion = English;
279 | hasScannedForEncodings = 0;
280 | knownRegions = (
281 | en,
282 | Base,
283 | );
284 | mainGroup = 6A2D6F681DD144A4008BA1C6;
285 | productRefGroup = 6A2D6F721DD144A4008BA1C6 /* Products */;
286 | projectDirPath = "";
287 | projectRoot = "";
288 | targets = (
289 | 6AF0EB281DDCD5A300F9506F /* SwiftyVIPERiOS */,
290 | 6AF0EB491DDCD94100F9506F /* SwiftyVIPERiOSTests */,
291 | 6A3037C41DDCDE2C0016B3E9 /* SwiftyVIPERtvOS */,
292 | 6A3037D41DDCE2160016B3E9 /* SwiftyVIPERtvOSTests */,
293 | );
294 | };
295 | /* End PBXProject section */
296 |
297 | /* Begin PBXResourcesBuildPhase section */
298 | 6A3037C31DDCDE2C0016B3E9 /* Resources */ = {
299 | isa = PBXResourcesBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | );
303 | runOnlyForDeploymentPostprocessing = 0;
304 | };
305 | 6A3037D31DDCE2160016B3E9 /* Resources */ = {
306 | isa = PBXResourcesBuildPhase;
307 | buildActionMask = 2147483647;
308 | files = (
309 | 6A3037E41DDCE3130016B3E9 /* tvOS.storyboard in Resources */,
310 | );
311 | runOnlyForDeploymentPostprocessing = 0;
312 | };
313 | 6AF0EB271DDCD5A300F9506F /* Resources */ = {
314 | isa = PBXResourcesBuildPhase;
315 | buildActionMask = 2147483647;
316 | files = (
317 | );
318 | runOnlyForDeploymentPostprocessing = 0;
319 | };
320 | 6AF0EB481DDCD94100F9506F /* Resources */ = {
321 | isa = PBXResourcesBuildPhase;
322 | buildActionMask = 2147483647;
323 | files = (
324 | 6AF0EB551DDCD98100F9506F /* iOS.storyboard in Resources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | /* End PBXResourcesBuildPhase section */
329 |
330 | /* Begin PBXShellScriptBuildPhase section */
331 | 6AA354C71E17838F00FB46AA /* Swift Lint */ = {
332 | isa = PBXShellScriptBuildPhase;
333 | buildActionMask = 2147483647;
334 | files = (
335 | );
336 | inputPaths = (
337 | );
338 | name = "Swift Lint";
339 | outputPaths = (
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | shellPath = /bin/sh;
343 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
344 | };
345 | 6AA354C81E1783A500FB46AA /* Swift Lint */ = {
346 | isa = PBXShellScriptBuildPhase;
347 | buildActionMask = 2147483647;
348 | files = (
349 | );
350 | inputPaths = (
351 | );
352 | name = "Swift Lint";
353 | outputPaths = (
354 | );
355 | runOnlyForDeploymentPostprocessing = 0;
356 | shellPath = /bin/sh;
357 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
358 | };
359 | /* End PBXShellScriptBuildPhase section */
360 |
361 | /* Begin PBXSourcesBuildPhase section */
362 | 6A3037C01DDCDE2C0016B3E9 /* Sources */ = {
363 | isa = PBXSourcesBuildPhase;
364 | buildActionMask = 2147483647;
365 | files = (
366 | 6A3037CF1DDCE1200016B3E9 /* Protocols.swift in Sources */,
367 | 6A3037D01DDCE1270016B3E9 /* Extensions.swift in Sources */,
368 | );
369 | runOnlyForDeploymentPostprocessing = 0;
370 | };
371 | 6A3037D11DDCE2160016B3E9 /* Sources */ = {
372 | isa = PBXSourcesBuildPhase;
373 | buildActionMask = 2147483647;
374 | files = (
375 | 6A3037E11DDCE2DD0016B3E9 /* ProtocolTests.swift in Sources */,
376 | 6A3037E21DDCE2DD0016B3E9 /* MockModule.swift in Sources */,
377 | );
378 | runOnlyForDeploymentPostprocessing = 0;
379 | };
380 | 6AF0EB241DDCD5A300F9506F /* Sources */ = {
381 | isa = PBXSourcesBuildPhase;
382 | buildActionMask = 2147483647;
383 | files = (
384 | 6AF0EB411DDCD8F300F9506F /* Protocols.swift in Sources */,
385 | 6AF0EB421DDCD8F300F9506F /* Extensions.swift in Sources */,
386 | );
387 | runOnlyForDeploymentPostprocessing = 0;
388 | };
389 | 6AF0EB461DDCD94100F9506F /* Sources */ = {
390 | isa = PBXSourcesBuildPhase;
391 | buildActionMask = 2147483647;
392 | files = (
393 | 6AF0EB561DDCD98100F9506F /* ProtocolTests.swift in Sources */,
394 | 6AF0EB571DDCD98100F9506F /* MockModule.swift in Sources */,
395 | );
396 | runOnlyForDeploymentPostprocessing = 0;
397 | };
398 | /* End PBXSourcesBuildPhase section */
399 |
400 | /* Begin PBXTargetDependency section */
401 | 6A3037DC1DDCE2160016B3E9 /* PBXTargetDependency */ = {
402 | isa = PBXTargetDependency;
403 | target = 6A3037C41DDCDE2C0016B3E9 /* SwiftyVIPERtvOS */;
404 | targetProxy = 6A3037DB1DDCE2160016B3E9 /* PBXContainerItemProxy */;
405 | };
406 | 6AF0EB511DDCD94100F9506F /* PBXTargetDependency */ = {
407 | isa = PBXTargetDependency;
408 | target = 6AF0EB281DDCD5A300F9506F /* SwiftyVIPERiOS */;
409 | targetProxy = 6AF0EB501DDCD94100F9506F /* PBXContainerItemProxy */;
410 | };
411 | /* End PBXTargetDependency section */
412 |
413 | /* Begin XCBuildConfiguration section */
414 | 6A2D6F8C1DD144A5008BA1C6 /* Debug */ = {
415 | isa = XCBuildConfiguration;
416 | buildSettings = {
417 | ALWAYS_SEARCH_USER_PATHS = NO;
418 | CLANG_ANALYZER_NONNULL = YES;
419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
420 | CLANG_CXX_LIBRARY = "libc++";
421 | CLANG_ENABLE_MODULES = YES;
422 | CLANG_ENABLE_OBJC_ARC = YES;
423 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
424 | CLANG_WARN_BOOL_CONVERSION = YES;
425 | CLANG_WARN_COMMA = YES;
426 | CLANG_WARN_CONSTANT_CONVERSION = YES;
427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
428 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
429 | CLANG_WARN_EMPTY_BODY = YES;
430 | CLANG_WARN_ENUM_CONVERSION = YES;
431 | CLANG_WARN_INFINITE_RECURSION = YES;
432 | CLANG_WARN_INT_CONVERSION = YES;
433 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
434 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
435 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
436 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
437 | CLANG_WARN_STRICT_PROTOTYPES = YES;
438 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
439 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
440 | CLANG_WARN_UNREACHABLE_CODE = YES;
441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
442 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
443 | COPY_PHASE_STRIP = NO;
444 | DEBUG_INFORMATION_FORMAT = dwarf;
445 | ENABLE_STRICT_OBJC_MSGSEND = YES;
446 | ENABLE_TESTABILITY = YES;
447 | GCC_C_LANGUAGE_STANDARD = gnu99;
448 | GCC_DYNAMIC_NO_PIC = NO;
449 | GCC_NO_COMMON_BLOCKS = YES;
450 | GCC_OPTIMIZATION_LEVEL = 0;
451 | GCC_PREPROCESSOR_DEFINITIONS = (
452 | "DEBUG=1",
453 | "$(inherited)",
454 | );
455 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
456 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
457 | GCC_WARN_UNDECLARED_SELECTOR = YES;
458 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
459 | GCC_WARN_UNUSED_FUNCTION = YES;
460 | GCC_WARN_UNUSED_VARIABLE = YES;
461 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
462 | MTL_ENABLE_DEBUG_INFO = YES;
463 | ONLY_ACTIVE_ARCH = YES;
464 | SDKROOT = iphoneos;
465 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
466 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
467 | };
468 | name = Debug;
469 | };
470 | 6A2D6F8D1DD144A5008BA1C6 /* Release */ = {
471 | isa = XCBuildConfiguration;
472 | buildSettings = {
473 | ALWAYS_SEARCH_USER_PATHS = NO;
474 | CLANG_ANALYZER_NONNULL = YES;
475 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
476 | CLANG_CXX_LIBRARY = "libc++";
477 | CLANG_ENABLE_MODULES = YES;
478 | CLANG_ENABLE_OBJC_ARC = YES;
479 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
480 | CLANG_WARN_BOOL_CONVERSION = YES;
481 | CLANG_WARN_COMMA = YES;
482 | CLANG_WARN_CONSTANT_CONVERSION = YES;
483 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
484 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
485 | CLANG_WARN_EMPTY_BODY = YES;
486 | CLANG_WARN_ENUM_CONVERSION = YES;
487 | CLANG_WARN_INFINITE_RECURSION = YES;
488 | CLANG_WARN_INT_CONVERSION = YES;
489 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
490 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
491 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
492 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
493 | CLANG_WARN_STRICT_PROTOTYPES = YES;
494 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
495 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
496 | CLANG_WARN_UNREACHABLE_CODE = YES;
497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
499 | COPY_PHASE_STRIP = NO;
500 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
501 | ENABLE_NS_ASSERTIONS = NO;
502 | ENABLE_STRICT_OBJC_MSGSEND = YES;
503 | GCC_C_LANGUAGE_STANDARD = gnu99;
504 | GCC_NO_COMMON_BLOCKS = YES;
505 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
506 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
507 | GCC_WARN_UNDECLARED_SELECTOR = YES;
508 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
509 | GCC_WARN_UNUSED_FUNCTION = YES;
510 | GCC_WARN_UNUSED_VARIABLE = YES;
511 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
512 | MTL_ENABLE_DEBUG_INFO = NO;
513 | SDKROOT = iphoneos;
514 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
515 | VALIDATE_PRODUCT = YES;
516 | };
517 | name = Release;
518 | };
519 | 6A3037CA1DDCDE2C0016B3E9 /* Debug */ = {
520 | isa = XCBuildConfiguration;
521 | buildSettings = {
522 | CODE_SIGN_IDENTITY = "";
523 | CURRENT_PROJECT_VERSION = 1;
524 | DEFINES_MODULE = YES;
525 | DEVELOPMENT_TEAM = FUC97LYJ62;
526 | DYLIB_COMPATIBILITY_VERSION = 1;
527 | DYLIB_CURRENT_VERSION = 1;
528 | DYLIB_INSTALL_NAME_BASE = "@rpath";
529 | INFOPLIST_FILE = Sources/Info.plist;
530 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
532 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPER;
533 | PRODUCT_NAME = SwiftyVIPER;
534 | SDKROOT = appletvos;
535 | SKIP_INSTALL = YES;
536 | SWIFT_VERSION = 4.0;
537 | TARGETED_DEVICE_FAMILY = 3;
538 | TVOS_DEPLOYMENT_TARGET = 9.0;
539 | VERSIONING_SYSTEM = "apple-generic";
540 | VERSION_INFO_PREFIX = "";
541 | };
542 | name = Debug;
543 | };
544 | 6A3037CB1DDCDE2C0016B3E9 /* Release */ = {
545 | isa = XCBuildConfiguration;
546 | buildSettings = {
547 | CODE_SIGN_IDENTITY = "";
548 | CURRENT_PROJECT_VERSION = 1;
549 | DEFINES_MODULE = YES;
550 | DEVELOPMENT_TEAM = FUC97LYJ62;
551 | DYLIB_COMPATIBILITY_VERSION = 1;
552 | DYLIB_CURRENT_VERSION = 1;
553 | DYLIB_INSTALL_NAME_BASE = "@rpath";
554 | INFOPLIST_FILE = Sources/Info.plist;
555 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
556 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
557 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPER;
558 | PRODUCT_NAME = SwiftyVIPER;
559 | SDKROOT = appletvos;
560 | SKIP_INSTALL = YES;
561 | SWIFT_VERSION = 4.0;
562 | TARGETED_DEVICE_FAMILY = 3;
563 | TVOS_DEPLOYMENT_TARGET = 9.0;
564 | VERSIONING_SYSTEM = "apple-generic";
565 | VERSION_INFO_PREFIX = "";
566 | };
567 | name = Release;
568 | };
569 | 6A3037DE1DDCE2160016B3E9 /* Debug */ = {
570 | isa = XCBuildConfiguration;
571 | buildSettings = {
572 | DEVELOPMENT_TEAM = FUC97LYJ62;
573 | INFOPLIST_FILE = Tests/Info.plist;
574 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
575 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERtvOSTests;
576 | PRODUCT_NAME = "$(TARGET_NAME)";
577 | SDKROOT = appletvos;
578 | SWIFT_VERSION = 4.0;
579 | TVOS_DEPLOYMENT_TARGET = 10.0;
580 | };
581 | name = Debug;
582 | };
583 | 6A3037DF1DDCE2160016B3E9 /* Release */ = {
584 | isa = XCBuildConfiguration;
585 | buildSettings = {
586 | DEVELOPMENT_TEAM = FUC97LYJ62;
587 | INFOPLIST_FILE = Tests/Info.plist;
588 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
589 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERtvOSTests;
590 | PRODUCT_NAME = "$(TARGET_NAME)";
591 | SDKROOT = appletvos;
592 | SWIFT_VERSION = 4.0;
593 | TVOS_DEPLOYMENT_TARGET = 10.0;
594 | };
595 | name = Release;
596 | };
597 | 6AF0EB3B1DDCD5A300F9506F /* Debug */ = {
598 | isa = XCBuildConfiguration;
599 | buildSettings = {
600 | CODE_SIGN_IDENTITY = "";
601 | CURRENT_PROJECT_VERSION = 1;
602 | DEFINES_MODULE = YES;
603 | DEVELOPMENT_TEAM = FUC97LYJ62;
604 | DYLIB_COMPATIBILITY_VERSION = 1;
605 | DYLIB_CURRENT_VERSION = 1;
606 | DYLIB_INSTALL_NAME_BASE = "@rpath";
607 | INFOPLIST_FILE = Sources/Info.plist;
608 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
609 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
610 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPER;
611 | PRODUCT_NAME = SwiftyVIPER;
612 | SKIP_INSTALL = YES;
613 | SWIFT_VERSION = 4.0;
614 | TARGETED_DEVICE_FAMILY = "1,2";
615 | VERSIONING_SYSTEM = "apple-generic";
616 | VERSION_INFO_PREFIX = "";
617 | };
618 | name = Debug;
619 | };
620 | 6AF0EB3C1DDCD5A300F9506F /* Release */ = {
621 | isa = XCBuildConfiguration;
622 | buildSettings = {
623 | CODE_SIGN_IDENTITY = "";
624 | CURRENT_PROJECT_VERSION = 1;
625 | DEFINES_MODULE = YES;
626 | DEVELOPMENT_TEAM = FUC97LYJ62;
627 | DYLIB_COMPATIBILITY_VERSION = 1;
628 | DYLIB_CURRENT_VERSION = 1;
629 | DYLIB_INSTALL_NAME_BASE = "@rpath";
630 | INFOPLIST_FILE = Sources/Info.plist;
631 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
632 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
633 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPER;
634 | PRODUCT_NAME = SwiftyVIPER;
635 | SKIP_INSTALL = YES;
636 | SWIFT_VERSION = 4.0;
637 | TARGETED_DEVICE_FAMILY = "1,2";
638 | VERSIONING_SYSTEM = "apple-generic";
639 | VERSION_INFO_PREFIX = "";
640 | };
641 | name = Release;
642 | };
643 | 6AF0EB531DDCD94100F9506F /* Debug */ = {
644 | isa = XCBuildConfiguration;
645 | buildSettings = {
646 | DEVELOPMENT_TEAM = FUC97LYJ62;
647 | INFOPLIST_FILE = Tests/Info.plist;
648 | IPHONEOS_DEPLOYMENT_TARGET = 10.1;
649 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
650 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERiOSTests;
651 | PRODUCT_NAME = "$(TARGET_NAME)";
652 | SWIFT_VERSION = 4.0;
653 | };
654 | name = Debug;
655 | };
656 | 6AF0EB541DDCD94100F9506F /* Release */ = {
657 | isa = XCBuildConfiguration;
658 | buildSettings = {
659 | DEVELOPMENT_TEAM = FUC97LYJ62;
660 | INFOPLIST_FILE = Tests/Info.plist;
661 | IPHONEOS_DEPLOYMENT_TARGET = 10.1;
662 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
663 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERiOSTests;
664 | PRODUCT_NAME = "$(TARGET_NAME)";
665 | SWIFT_VERSION = 4.0;
666 | };
667 | name = Release;
668 | };
669 | /* End XCBuildConfiguration section */
670 |
671 | /* Begin XCConfigurationList section */
672 | 6A2D6F6C1DD144A4008BA1C6 /* Build configuration list for PBXProject "SwiftyVIPER" */ = {
673 | isa = XCConfigurationList;
674 | buildConfigurations = (
675 | 6A2D6F8C1DD144A5008BA1C6 /* Debug */,
676 | 6A2D6F8D1DD144A5008BA1C6 /* Release */,
677 | );
678 | defaultConfigurationIsVisible = 0;
679 | defaultConfigurationName = Release;
680 | };
681 | 6A3037CC1DDCDE2C0016B3E9 /* Build configuration list for PBXNativeTarget "SwiftyVIPERtvOS" */ = {
682 | isa = XCConfigurationList;
683 | buildConfigurations = (
684 | 6A3037CA1DDCDE2C0016B3E9 /* Debug */,
685 | 6A3037CB1DDCDE2C0016B3E9 /* Release */,
686 | );
687 | defaultConfigurationIsVisible = 0;
688 | defaultConfigurationName = Release;
689 | };
690 | 6A3037DD1DDCE2160016B3E9 /* Build configuration list for PBXNativeTarget "SwiftyVIPERtvOSTests" */ = {
691 | isa = XCConfigurationList;
692 | buildConfigurations = (
693 | 6A3037DE1DDCE2160016B3E9 /* Debug */,
694 | 6A3037DF1DDCE2160016B3E9 /* Release */,
695 | );
696 | defaultConfigurationIsVisible = 0;
697 | defaultConfigurationName = Release;
698 | };
699 | 6AF0EB3A1DDCD5A300F9506F /* Build configuration list for PBXNativeTarget "SwiftyVIPERiOS" */ = {
700 | isa = XCConfigurationList;
701 | buildConfigurations = (
702 | 6AF0EB3B1DDCD5A300F9506F /* Debug */,
703 | 6AF0EB3C1DDCD5A300F9506F /* Release */,
704 | );
705 | defaultConfigurationIsVisible = 0;
706 | defaultConfigurationName = Release;
707 | };
708 | 6AF0EB521DDCD94100F9506F /* Build configuration list for PBXNativeTarget "SwiftyVIPERiOSTests" */ = {
709 | isa = XCConfigurationList;
710 | buildConfigurations = (
711 | 6AF0EB531DDCD94100F9506F /* Debug */,
712 | 6AF0EB541DDCD94100F9506F /* Release */,
713 | );
714 | defaultConfigurationIsVisible = 0;
715 | defaultConfigurationName = Release;
716 | };
717 | /* End XCConfigurationList section */
718 | };
719 | rootObject = 6A2D6F691DD144A4008BA1C6 /* Project object */;
720 | }
721 |
--------------------------------------------------------------------------------
/Example/SwiftyVIPERExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 51E92D3E993B4BA76E5C7B18 /* Pods_SwiftyVIPERExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B74346C9D995D2C40047586 /* Pods_SwiftyVIPERExample.framework */; };
11 | 6A0E81121DD13FAE006B1A61 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E81111DD13FAE006B1A61 /* AppDelegate.swift */; };
12 | 6A0E81191DD13FAE006B1A61 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A0E81181DD13FAE006B1A61 /* Assets.xcassets */; };
13 | 6A0E81321DD1400D006B1A61 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6A0E81311DD1400D006B1A61 /* LaunchScreen.storyboard */; };
14 | 6A0E81431DD14048006B1A61 /* RootInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E81391DD14048006B1A61 /* RootInteractor.swift */; };
15 | 6A0E81441DD14048006B1A61 /* RootModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E813A1DD14048006B1A61 /* RootModule.swift */; };
16 | 6A0E81451DD14048006B1A61 /* RootPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E813B1DD14048006B1A61 /* RootPresenter.swift */; };
17 | 6A0E81461DD14048006B1A61 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E813C1DD14048006B1A61 /* RootRouter.swift */; };
18 | 6A0E81471DD14048006B1A61 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A0E813D1DD14048006B1A61 /* RootViewController.swift */; };
19 | 6A24A9E21DD3D8E40092B050 /* DetailInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9DD1DD3D8E40092B050 /* DetailInteractor.swift */; };
20 | 6A24A9E31DD3D8E40092B050 /* DetailModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9DE1DD3D8E40092B050 /* DetailModule.swift */; };
21 | 6A24A9E41DD3D8E40092B050 /* DetailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9DF1DD3D8E40092B050 /* DetailPresenter.swift */; };
22 | 6A24A9E51DD3D8E40092B050 /* DetailRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9E01DD3D8E40092B050 /* DetailRouter.swift */; };
23 | 6A24A9E61DD3D8E40092B050 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9E11DD3D8E40092B050 /* DetailViewController.swift */; };
24 | 6A24A9E81DD3D9310092B050 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6A24A9E71DD3D9310092B050 /* Main.storyboard */; };
25 | 6A24A9EF1DD3E23E0092B050 /* DetailInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9EA1DD3E23E0092B050 /* DetailInteractorTests.swift */; };
26 | 6A24A9F01DD3E23E0092B050 /* DetailModuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9EB1DD3E23E0092B050 /* DetailModuleTests.swift */; };
27 | 6A24A9F11DD3E23E0092B050 /* DetailPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9EC1DD3E23E0092B050 /* DetailPresenterTests.swift */; };
28 | 6A24A9F21DD3E23E0092B050 /* DetailRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9ED1DD3E23E0092B050 /* DetailRouterTests.swift */; };
29 | 6A24A9F31DD3E23E0092B050 /* DetailViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9EE1DD3E23E0092B050 /* DetailViewTests.swift */; };
30 | 6A24A9FB1DD3E84C0092B050 /* RootInteractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9F51DD3E84C0092B050 /* RootInteractorTests.swift */; };
31 | 6A24A9FC1DD3E84C0092B050 /* RootModuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9F61DD3E84C0092B050 /* RootModuleTests.swift */; };
32 | 6A24A9FD1DD3E84C0092B050 /* RootPresenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9F71DD3E84C0092B050 /* RootPresenterTests.swift */; };
33 | 6A24A9FE1DD3E84C0092B050 /* RootRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9F81DD3E84C0092B050 /* RootRouterTests.swift */; };
34 | 6A24AA001DD3E84C0092B050 /* RootViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A24A9FA1DD3E84C0092B050 /* RootViewTests.swift */; };
35 | 72DCFF4D795D983E7C286884 /* Pods_SwiftyVIPERExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89449D402B006941B3E7BCDE /* Pods_SwiftyVIPERExampleTests.framework */; };
36 | /* End PBXBuildFile section */
37 |
38 | /* Begin PBXContainerItemProxy section */
39 | 6A0E81231DD13FAE006B1A61 /* PBXContainerItemProxy */ = {
40 | isa = PBXContainerItemProxy;
41 | containerPortal = 6A0E81061DD13FAE006B1A61 /* Project object */;
42 | proxyType = 1;
43 | remoteGlobalIDString = 6A0E810D1DD13FAE006B1A61;
44 | remoteInfo = SwiftyVIPERExample;
45 | };
46 | /* End PBXContainerItemProxy section */
47 |
48 | /* Begin PBXFileReference section */
49 | 6A0E810E1DD13FAE006B1A61 /* SwiftyVIPERExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftyVIPERExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 6A0E81111DD13FAE006B1A61 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
51 | 6A0E81181DD13FAE006B1A61 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
52 | 6A0E811D1DD13FAE006B1A61 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | 6A0E81221DD13FAE006B1A61 /* SwiftyVIPERExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftyVIPERExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 6A0E81281DD13FAE006B1A61 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
55 | 6A0E81311DD1400D006B1A61 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
56 | 6A0E81391DD14048006B1A61 /* RootInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootInteractor.swift; sourceTree = ""; };
57 | 6A0E813A1DD14048006B1A61 /* RootModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootModule.swift; sourceTree = ""; };
58 | 6A0E813B1DD14048006B1A61 /* RootPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootPresenter.swift; sourceTree = ""; };
59 | 6A0E813C1DD14048006B1A61 /* RootRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = ""; };
60 | 6A0E813D1DD14048006B1A61 /* RootViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; };
61 | 6A24A9DD1DD3D8E40092B050 /* DetailInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailInteractor.swift; sourceTree = ""; };
62 | 6A24A9DE1DD3D8E40092B050 /* DetailModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailModule.swift; sourceTree = ""; };
63 | 6A24A9DF1DD3D8E40092B050 /* DetailPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailPresenter.swift; sourceTree = ""; };
64 | 6A24A9E01DD3D8E40092B050 /* DetailRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailRouter.swift; sourceTree = ""; };
65 | 6A24A9E11DD3D8E40092B050 /* DetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; };
66 | 6A24A9E71DD3D9310092B050 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
67 | 6A24A9EA1DD3E23E0092B050 /* DetailInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailInteractorTests.swift; sourceTree = ""; };
68 | 6A24A9EB1DD3E23E0092B050 /* DetailModuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailModuleTests.swift; sourceTree = ""; };
69 | 6A24A9EC1DD3E23E0092B050 /* DetailPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailPresenterTests.swift; sourceTree = ""; };
70 | 6A24A9ED1DD3E23E0092B050 /* DetailRouterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailRouterTests.swift; sourceTree = ""; };
71 | 6A24A9EE1DD3E23E0092B050 /* DetailViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailViewTests.swift; sourceTree = ""; };
72 | 6A24A9F51DD3E84C0092B050 /* RootInteractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootInteractorTests.swift; sourceTree = ""; };
73 | 6A24A9F61DD3E84C0092B050 /* RootModuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootModuleTests.swift; sourceTree = ""; };
74 | 6A24A9F71DD3E84C0092B050 /* RootPresenterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootPresenterTests.swift; sourceTree = ""; };
75 | 6A24A9F81DD3E84C0092B050 /* RootRouterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootRouterTests.swift; sourceTree = ""; };
76 | 6A24A9FA1DD3E84C0092B050 /* RootViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootViewTests.swift; sourceTree = ""; };
77 | 7B13EB3C0E109B519EAC7538 /* Pods-SwiftyVIPERExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyVIPERExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyVIPERExampleTests/Pods-SwiftyVIPERExampleTests.release.xcconfig"; sourceTree = ""; };
78 | 7B62C270AE3AE7163DD700D6 /* Pods-SwiftyVIPERExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyVIPERExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyVIPERExample/Pods-SwiftyVIPERExample.release.xcconfig"; sourceTree = ""; };
79 | 89449D402B006941B3E7BCDE /* Pods_SwiftyVIPERExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftyVIPERExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80 | 8F40ACE46DDE6AFE65773867 /* Pods-SwiftyVIPERExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyVIPERExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyVIPERExampleTests/Pods-SwiftyVIPERExampleTests.debug.xcconfig"; sourceTree = ""; };
81 | 90F933D5C30B23C93C04943F /* Pods-SwiftyVIPERExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftyVIPERExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftyVIPERExample/Pods-SwiftyVIPERExample.debug.xcconfig"; sourceTree = ""; };
82 | 9B74346C9D995D2C40047586 /* Pods_SwiftyVIPERExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftyVIPERExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83 | /* End PBXFileReference section */
84 |
85 | /* Begin PBXFrameworksBuildPhase section */
86 | 6A0E810B1DD13FAE006B1A61 /* Frameworks */ = {
87 | isa = PBXFrameworksBuildPhase;
88 | buildActionMask = 2147483647;
89 | files = (
90 | 51E92D3E993B4BA76E5C7B18 /* Pods_SwiftyVIPERExample.framework in Frameworks */,
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | 6A0E811F1DD13FAE006B1A61 /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | 72DCFF4D795D983E7C286884 /* Pods_SwiftyVIPERExampleTests.framework in Frameworks */,
99 | );
100 | runOnlyForDeploymentPostprocessing = 0;
101 | };
102 | /* End PBXFrameworksBuildPhase section */
103 |
104 | /* Begin PBXGroup section */
105 | 4E83E6E8F74A67F5CE5C168A /* Pods */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 90F933D5C30B23C93C04943F /* Pods-SwiftyVIPERExample.debug.xcconfig */,
109 | 7B62C270AE3AE7163DD700D6 /* Pods-SwiftyVIPERExample.release.xcconfig */,
110 | 8F40ACE46DDE6AFE65773867 /* Pods-SwiftyVIPERExampleTests.debug.xcconfig */,
111 | 7B13EB3C0E109B519EAC7538 /* Pods-SwiftyVIPERExampleTests.release.xcconfig */,
112 | );
113 | name = Pods;
114 | sourceTree = "";
115 | };
116 | 6A0E81051DD13FAE006B1A61 = {
117 | isa = PBXGroup;
118 | children = (
119 | 6A0E81101DD13FAE006B1A61 /* SwiftyVIPERExample */,
120 | 6A0E81251DD13FAE006B1A61 /* SwiftyVIPERExampleTests */,
121 | 6A0E810F1DD13FAE006B1A61 /* Products */,
122 | 4E83E6E8F74A67F5CE5C168A /* Pods */,
123 | CA1ABAFCCB4689C070AEE031 /* Frameworks */,
124 | );
125 | sourceTree = "";
126 | };
127 | 6A0E810F1DD13FAE006B1A61 /* Products */ = {
128 | isa = PBXGroup;
129 | children = (
130 | 6A0E810E1DD13FAE006B1A61 /* SwiftyVIPERExample.app */,
131 | 6A0E81221DD13FAE006B1A61 /* SwiftyVIPERExampleTests.xctest */,
132 | );
133 | name = Products;
134 | sourceTree = "";
135 | };
136 | 6A0E81101DD13FAE006B1A61 /* SwiftyVIPERExample */ = {
137 | isa = PBXGroup;
138 | children = (
139 | 6A0E811D1DD13FAE006B1A61 /* Info.plist */,
140 | 6A24A9E71DD3D9310092B050 /* Main.storyboard */,
141 | 6A0E81311DD1400D006B1A61 /* LaunchScreen.storyboard */,
142 | 6A0E81111DD13FAE006B1A61 /* AppDelegate.swift */,
143 | 6A0E81181DD13FAE006B1A61 /* Assets.xcassets */,
144 | 6A0E81331DD14048006B1A61 /* Modules */,
145 | );
146 | path = SwiftyVIPERExample;
147 | sourceTree = "";
148 | };
149 | 6A0E81251DD13FAE006B1A61 /* SwiftyVIPERExampleTests */ = {
150 | isa = PBXGroup;
151 | children = (
152 | 6A24A9F41DD3E83E0092B050 /* Root */,
153 | 6A24A9E91DD3E22A0092B050 /* Detail */,
154 | 6A0E81281DD13FAE006B1A61 /* Info.plist */,
155 | );
156 | path = SwiftyVIPERExampleTests;
157 | sourceTree = "";
158 | };
159 | 6A0E81331DD14048006B1A61 /* Modules */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 6A2D6F651DD14296008BA1C6 /* Root */,
163 | 6A24A9DC1DD3D8D60092B050 /* Detail */,
164 | );
165 | path = Modules;
166 | sourceTree = "";
167 | };
168 | 6A24A9DC1DD3D8D60092B050 /* Detail */ = {
169 | isa = PBXGroup;
170 | children = (
171 | 6A24A9DD1DD3D8E40092B050 /* DetailInteractor.swift */,
172 | 6A24A9DE1DD3D8E40092B050 /* DetailModule.swift */,
173 | 6A24A9DF1DD3D8E40092B050 /* DetailPresenter.swift */,
174 | 6A24A9E01DD3D8E40092B050 /* DetailRouter.swift */,
175 | 6A24A9E11DD3D8E40092B050 /* DetailViewController.swift */,
176 | );
177 | name = Detail;
178 | sourceTree = "";
179 | };
180 | 6A24A9E91DD3E22A0092B050 /* Detail */ = {
181 | isa = PBXGroup;
182 | children = (
183 | 6A24A9EA1DD3E23E0092B050 /* DetailInteractorTests.swift */,
184 | 6A24A9EB1DD3E23E0092B050 /* DetailModuleTests.swift */,
185 | 6A24A9EC1DD3E23E0092B050 /* DetailPresenterTests.swift */,
186 | 6A24A9ED1DD3E23E0092B050 /* DetailRouterTests.swift */,
187 | 6A24A9EE1DD3E23E0092B050 /* DetailViewTests.swift */,
188 | );
189 | name = Detail;
190 | sourceTree = "";
191 | };
192 | 6A24A9F41DD3E83E0092B050 /* Root */ = {
193 | isa = PBXGroup;
194 | children = (
195 | 6A24A9F51DD3E84C0092B050 /* RootInteractorTests.swift */,
196 | 6A24A9F61DD3E84C0092B050 /* RootModuleTests.swift */,
197 | 6A24A9F71DD3E84C0092B050 /* RootPresenterTests.swift */,
198 | 6A24A9F81DD3E84C0092B050 /* RootRouterTests.swift */,
199 | 6A24A9FA1DD3E84C0092B050 /* RootViewTests.swift */,
200 | );
201 | name = Root;
202 | sourceTree = "";
203 | };
204 | 6A2D6F651DD14296008BA1C6 /* Root */ = {
205 | isa = PBXGroup;
206 | children = (
207 | 6A0E813A1DD14048006B1A61 /* RootModule.swift */,
208 | 6A0E813D1DD14048006B1A61 /* RootViewController.swift */,
209 | 6A0E813B1DD14048006B1A61 /* RootPresenter.swift */,
210 | 6A0E813C1DD14048006B1A61 /* RootRouter.swift */,
211 | 6A0E81391DD14048006B1A61 /* RootInteractor.swift */,
212 | );
213 | name = Root;
214 | sourceTree = "";
215 | };
216 | CA1ABAFCCB4689C070AEE031 /* Frameworks */ = {
217 | isa = PBXGroup;
218 | children = (
219 | 9B74346C9D995D2C40047586 /* Pods_SwiftyVIPERExample.framework */,
220 | 89449D402B006941B3E7BCDE /* Pods_SwiftyVIPERExampleTests.framework */,
221 | );
222 | name = Frameworks;
223 | sourceTree = "";
224 | };
225 | /* End PBXGroup section */
226 |
227 | /* Begin PBXNativeTarget section */
228 | 6A0E810D1DD13FAE006B1A61 /* SwiftyVIPERExample */ = {
229 | isa = PBXNativeTarget;
230 | buildConfigurationList = 6A0E812B1DD13FAE006B1A61 /* Build configuration list for PBXNativeTarget "SwiftyVIPERExample" */;
231 | buildPhases = (
232 | CB08A14374F47E6A3B114DFA /* [CP] Check Pods Manifest.lock */,
233 | 6A6F42BF1E205CA3009E83A3 /* Swift Lint */,
234 | 6A0E810A1DD13FAE006B1A61 /* Sources */,
235 | 6A0E810B1DD13FAE006B1A61 /* Frameworks */,
236 | 6A0E810C1DD13FAE006B1A61 /* Resources */,
237 | EB34CCADA889999054950BFB /* [CP] Embed Pods Frameworks */,
238 | B0B2CC1FD9C3BDB42B539857 /* [CP] Copy Pods Resources */,
239 | );
240 | buildRules = (
241 | );
242 | dependencies = (
243 | );
244 | name = SwiftyVIPERExample;
245 | productName = SwiftyVIPERExample;
246 | productReference = 6A0E810E1DD13FAE006B1A61 /* SwiftyVIPERExample.app */;
247 | productType = "com.apple.product-type.application";
248 | };
249 | 6A0E81211DD13FAE006B1A61 /* SwiftyVIPERExampleTests */ = {
250 | isa = PBXNativeTarget;
251 | buildConfigurationList = 6A0E812E1DD13FAE006B1A61 /* Build configuration list for PBXNativeTarget "SwiftyVIPERExampleTests" */;
252 | buildPhases = (
253 | 33E33358867EA1F8D5E3D4AB /* [CP] Check Pods Manifest.lock */,
254 | 6A0E811E1DD13FAE006B1A61 /* Sources */,
255 | 6A0E811F1DD13FAE006B1A61 /* Frameworks */,
256 | 6A0E81201DD13FAE006B1A61 /* Resources */,
257 | F1C81699BC04C7B39DB8733F /* [CP] Embed Pods Frameworks */,
258 | BEDC2A6113592CA816BFD9F0 /* [CP] Copy Pods Resources */,
259 | );
260 | buildRules = (
261 | );
262 | dependencies = (
263 | 6A0E81241DD13FAE006B1A61 /* PBXTargetDependency */,
264 | );
265 | name = SwiftyVIPERExampleTests;
266 | productName = SwiftyVIPERExampleTests;
267 | productReference = 6A0E81221DD13FAE006B1A61 /* SwiftyVIPERExampleTests.xctest */;
268 | productType = "com.apple.product-type.bundle.unit-test";
269 | };
270 | /* End PBXNativeTarget section */
271 |
272 | /* Begin PBXProject section */
273 | 6A0E81061DD13FAE006B1A61 /* Project object */ = {
274 | isa = PBXProject;
275 | attributes = {
276 | LastSwiftUpdateCheck = 0810;
277 | LastUpgradeCheck = 0910;
278 | ORGANIZATIONNAME = codeRed;
279 | TargetAttributes = {
280 | 6A0E810D1DD13FAE006B1A61 = {
281 | CreatedOnToolsVersion = 8.1;
282 | DevelopmentTeam = FUC97LYJ62;
283 | LastSwiftMigration = 0910;
284 | ProvisioningStyle = Automatic;
285 | };
286 | 6A0E81211DD13FAE006B1A61 = {
287 | CreatedOnToolsVersion = 8.1;
288 | DevelopmentTeam = FUC97LYJ62;
289 | LastSwiftMigration = 0910;
290 | ProvisioningStyle = Automatic;
291 | TestTargetID = 6A0E810D1DD13FAE006B1A61;
292 | };
293 | };
294 | };
295 | buildConfigurationList = 6A0E81091DD13FAE006B1A61 /* Build configuration list for PBXProject "SwiftyVIPERExample" */;
296 | compatibilityVersion = "Xcode 3.2";
297 | developmentRegion = English;
298 | hasScannedForEncodings = 0;
299 | knownRegions = (
300 | en,
301 | Base,
302 | );
303 | mainGroup = 6A0E81051DD13FAE006B1A61;
304 | productRefGroup = 6A0E810F1DD13FAE006B1A61 /* Products */;
305 | projectDirPath = "";
306 | projectRoot = "";
307 | targets = (
308 | 6A0E810D1DD13FAE006B1A61 /* SwiftyVIPERExample */,
309 | 6A0E81211DD13FAE006B1A61 /* SwiftyVIPERExampleTests */,
310 | );
311 | };
312 | /* End PBXProject section */
313 |
314 | /* Begin PBXResourcesBuildPhase section */
315 | 6A0E810C1DD13FAE006B1A61 /* Resources */ = {
316 | isa = PBXResourcesBuildPhase;
317 | buildActionMask = 2147483647;
318 | files = (
319 | 6A24A9E81DD3D9310092B050 /* Main.storyboard in Resources */,
320 | 6A0E81191DD13FAE006B1A61 /* Assets.xcassets in Resources */,
321 | 6A0E81321DD1400D006B1A61 /* LaunchScreen.storyboard in Resources */,
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | };
325 | 6A0E81201DD13FAE006B1A61 /* Resources */ = {
326 | isa = PBXResourcesBuildPhase;
327 | buildActionMask = 2147483647;
328 | files = (
329 | );
330 | runOnlyForDeploymentPostprocessing = 0;
331 | };
332 | /* End PBXResourcesBuildPhase section */
333 |
334 | /* Begin PBXShellScriptBuildPhase section */
335 | 33E33358867EA1F8D5E3D4AB /* [CP] Check Pods Manifest.lock */ = {
336 | isa = PBXShellScriptBuildPhase;
337 | buildActionMask = 2147483647;
338 | files = (
339 | );
340 | inputPaths = (
341 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
342 | "${PODS_ROOT}/Manifest.lock",
343 | );
344 | name = "[CP] Check Pods Manifest.lock";
345 | outputPaths = (
346 | "$(DERIVED_FILE_DIR)/Pods-SwiftyVIPERExampleTests-checkManifestLockResult.txt",
347 | );
348 | runOnlyForDeploymentPostprocessing = 0;
349 | shellPath = /bin/sh;
350 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
351 | showEnvVarsInLog = 0;
352 | };
353 | 6A6F42BF1E205CA3009E83A3 /* Swift Lint */ = {
354 | isa = PBXShellScriptBuildPhase;
355 | buildActionMask = 2147483647;
356 | files = (
357 | );
358 | inputPaths = (
359 | );
360 | name = "Swift Lint";
361 | outputPaths = (
362 | );
363 | runOnlyForDeploymentPostprocessing = 0;
364 | shellPath = /bin/sh;
365 | shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi";
366 | };
367 | B0B2CC1FD9C3BDB42B539857 /* [CP] Copy Pods Resources */ = {
368 | isa = PBXShellScriptBuildPhase;
369 | buildActionMask = 2147483647;
370 | files = (
371 | );
372 | inputPaths = (
373 | );
374 | name = "[CP] Copy Pods Resources";
375 | outputPaths = (
376 | );
377 | runOnlyForDeploymentPostprocessing = 0;
378 | shellPath = /bin/sh;
379 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExample/Pods-SwiftyVIPERExample-resources.sh\"\n";
380 | showEnvVarsInLog = 0;
381 | };
382 | BEDC2A6113592CA816BFD9F0 /* [CP] Copy Pods Resources */ = {
383 | isa = PBXShellScriptBuildPhase;
384 | buildActionMask = 2147483647;
385 | files = (
386 | );
387 | inputPaths = (
388 | );
389 | name = "[CP] Copy Pods Resources";
390 | outputPaths = (
391 | );
392 | runOnlyForDeploymentPostprocessing = 0;
393 | shellPath = /bin/sh;
394 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExampleTests/Pods-SwiftyVIPERExampleTests-resources.sh\"\n";
395 | showEnvVarsInLog = 0;
396 | };
397 | CB08A14374F47E6A3B114DFA /* [CP] Check Pods Manifest.lock */ = {
398 | isa = PBXShellScriptBuildPhase;
399 | buildActionMask = 2147483647;
400 | files = (
401 | );
402 | inputPaths = (
403 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
404 | "${PODS_ROOT}/Manifest.lock",
405 | );
406 | name = "[CP] Check Pods Manifest.lock";
407 | outputPaths = (
408 | "$(DERIVED_FILE_DIR)/Pods-SwiftyVIPERExample-checkManifestLockResult.txt",
409 | );
410 | runOnlyForDeploymentPostprocessing = 0;
411 | shellPath = /bin/sh;
412 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
413 | showEnvVarsInLog = 0;
414 | };
415 | EB34CCADA889999054950BFB /* [CP] Embed Pods Frameworks */ = {
416 | isa = PBXShellScriptBuildPhase;
417 | buildActionMask = 2147483647;
418 | files = (
419 | );
420 | inputPaths = (
421 | "${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExample/Pods-SwiftyVIPERExample-frameworks.sh",
422 | "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
423 | "${BUILT_PRODUCTS_DIR}/SwiftyVIPER/SwiftyVIPER.framework",
424 | );
425 | name = "[CP] Embed Pods Frameworks";
426 | outputPaths = (
427 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
428 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyVIPER.framework",
429 | );
430 | runOnlyForDeploymentPostprocessing = 0;
431 | shellPath = /bin/sh;
432 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExample/Pods-SwiftyVIPERExample-frameworks.sh\"\n";
433 | showEnvVarsInLog = 0;
434 | };
435 | F1C81699BC04C7B39DB8733F /* [CP] Embed Pods Frameworks */ = {
436 | isa = PBXShellScriptBuildPhase;
437 | buildActionMask = 2147483647;
438 | files = (
439 | );
440 | inputPaths = (
441 | "${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExampleTests/Pods-SwiftyVIPERExampleTests-frameworks.sh",
442 | "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework",
443 | "${BUILT_PRODUCTS_DIR}/SwiftyVIPER/SwiftyVIPER.framework",
444 | );
445 | name = "[CP] Embed Pods Frameworks";
446 | outputPaths = (
447 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework",
448 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyVIPER.framework",
449 | );
450 | runOnlyForDeploymentPostprocessing = 0;
451 | shellPath = /bin/sh;
452 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftyVIPERExampleTests/Pods-SwiftyVIPERExampleTests-frameworks.sh\"\n";
453 | showEnvVarsInLog = 0;
454 | };
455 | /* End PBXShellScriptBuildPhase section */
456 |
457 | /* Begin PBXSourcesBuildPhase section */
458 | 6A0E810A1DD13FAE006B1A61 /* Sources */ = {
459 | isa = PBXSourcesBuildPhase;
460 | buildActionMask = 2147483647;
461 | files = (
462 | 6A24A9E61DD3D8E40092B050 /* DetailViewController.swift in Sources */,
463 | 6A0E81451DD14048006B1A61 /* RootPresenter.swift in Sources */,
464 | 6A0E81471DD14048006B1A61 /* RootViewController.swift in Sources */,
465 | 6A24A9E41DD3D8E40092B050 /* DetailPresenter.swift in Sources */,
466 | 6A0E81441DD14048006B1A61 /* RootModule.swift in Sources */,
467 | 6A0E81121DD13FAE006B1A61 /* AppDelegate.swift in Sources */,
468 | 6A24A9E51DD3D8E40092B050 /* DetailRouter.swift in Sources */,
469 | 6A24A9E21DD3D8E40092B050 /* DetailInteractor.swift in Sources */,
470 | 6A0E81461DD14048006B1A61 /* RootRouter.swift in Sources */,
471 | 6A24A9E31DD3D8E40092B050 /* DetailModule.swift in Sources */,
472 | 6A0E81431DD14048006B1A61 /* RootInteractor.swift in Sources */,
473 | );
474 | runOnlyForDeploymentPostprocessing = 0;
475 | };
476 | 6A0E811E1DD13FAE006B1A61 /* Sources */ = {
477 | isa = PBXSourcesBuildPhase;
478 | buildActionMask = 2147483647;
479 | files = (
480 | 6A24A9F21DD3E23E0092B050 /* DetailRouterTests.swift in Sources */,
481 | 6A24A9FC1DD3E84C0092B050 /* RootModuleTests.swift in Sources */,
482 | 6A24A9FD1DD3E84C0092B050 /* RootPresenterTests.swift in Sources */,
483 | 6A24A9F31DD3E23E0092B050 /* DetailViewTests.swift in Sources */,
484 | 6A24A9FB1DD3E84C0092B050 /* RootInteractorTests.swift in Sources */,
485 | 6A24A9F11DD3E23E0092B050 /* DetailPresenterTests.swift in Sources */,
486 | 6A24A9FE1DD3E84C0092B050 /* RootRouterTests.swift in Sources */,
487 | 6A24A9F01DD3E23E0092B050 /* DetailModuleTests.swift in Sources */,
488 | 6A24AA001DD3E84C0092B050 /* RootViewTests.swift in Sources */,
489 | 6A24A9EF1DD3E23E0092B050 /* DetailInteractorTests.swift in Sources */,
490 | );
491 | runOnlyForDeploymentPostprocessing = 0;
492 | };
493 | /* End PBXSourcesBuildPhase section */
494 |
495 | /* Begin PBXTargetDependency section */
496 | 6A0E81241DD13FAE006B1A61 /* PBXTargetDependency */ = {
497 | isa = PBXTargetDependency;
498 | target = 6A0E810D1DD13FAE006B1A61 /* SwiftyVIPERExample */;
499 | targetProxy = 6A0E81231DD13FAE006B1A61 /* PBXContainerItemProxy */;
500 | };
501 | /* End PBXTargetDependency section */
502 |
503 | /* Begin XCBuildConfiguration section */
504 | 6A0E81291DD13FAE006B1A61 /* Debug */ = {
505 | isa = XCBuildConfiguration;
506 | buildSettings = {
507 | ALWAYS_SEARCH_USER_PATHS = NO;
508 | CLANG_ANALYZER_NONNULL = YES;
509 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
510 | CLANG_CXX_LIBRARY = "libc++";
511 | CLANG_ENABLE_MODULES = YES;
512 | CLANG_ENABLE_OBJC_ARC = YES;
513 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
514 | CLANG_WARN_BOOL_CONVERSION = YES;
515 | CLANG_WARN_COMMA = YES;
516 | CLANG_WARN_CONSTANT_CONVERSION = YES;
517 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
518 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
519 | CLANG_WARN_EMPTY_BODY = YES;
520 | CLANG_WARN_ENUM_CONVERSION = YES;
521 | CLANG_WARN_INFINITE_RECURSION = YES;
522 | CLANG_WARN_INT_CONVERSION = YES;
523 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
524 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
525 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
526 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
527 | CLANG_WARN_STRICT_PROTOTYPES = YES;
528 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
529 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
530 | CLANG_WARN_UNREACHABLE_CODE = YES;
531 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
532 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
533 | COPY_PHASE_STRIP = NO;
534 | DEBUG_INFORMATION_FORMAT = dwarf;
535 | ENABLE_STRICT_OBJC_MSGSEND = YES;
536 | ENABLE_TESTABILITY = YES;
537 | GCC_C_LANGUAGE_STANDARD = gnu99;
538 | GCC_DYNAMIC_NO_PIC = NO;
539 | GCC_NO_COMMON_BLOCKS = YES;
540 | GCC_OPTIMIZATION_LEVEL = 0;
541 | GCC_PREPROCESSOR_DEFINITIONS = (
542 | "DEBUG=1",
543 | "$(inherited)",
544 | );
545 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
546 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
547 | GCC_WARN_UNDECLARED_SELECTOR = YES;
548 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
549 | GCC_WARN_UNUSED_FUNCTION = YES;
550 | GCC_WARN_UNUSED_VARIABLE = YES;
551 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
552 | MTL_ENABLE_DEBUG_INFO = YES;
553 | ONLY_ACTIVE_ARCH = YES;
554 | SDKROOT = iphoneos;
555 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
556 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
557 | };
558 | name = Debug;
559 | };
560 | 6A0E812A1DD13FAE006B1A61 /* Release */ = {
561 | isa = XCBuildConfiguration;
562 | buildSettings = {
563 | ALWAYS_SEARCH_USER_PATHS = NO;
564 | CLANG_ANALYZER_NONNULL = YES;
565 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
566 | CLANG_CXX_LIBRARY = "libc++";
567 | CLANG_ENABLE_MODULES = YES;
568 | CLANG_ENABLE_OBJC_ARC = YES;
569 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
570 | CLANG_WARN_BOOL_CONVERSION = YES;
571 | CLANG_WARN_COMMA = YES;
572 | CLANG_WARN_CONSTANT_CONVERSION = YES;
573 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
574 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
575 | CLANG_WARN_EMPTY_BODY = YES;
576 | CLANG_WARN_ENUM_CONVERSION = YES;
577 | CLANG_WARN_INFINITE_RECURSION = YES;
578 | CLANG_WARN_INT_CONVERSION = YES;
579 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
580 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
581 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
582 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
583 | CLANG_WARN_STRICT_PROTOTYPES = YES;
584 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
585 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
586 | CLANG_WARN_UNREACHABLE_CODE = YES;
587 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
588 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
589 | COPY_PHASE_STRIP = NO;
590 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
591 | ENABLE_NS_ASSERTIONS = NO;
592 | ENABLE_STRICT_OBJC_MSGSEND = YES;
593 | GCC_C_LANGUAGE_STANDARD = gnu99;
594 | GCC_NO_COMMON_BLOCKS = YES;
595 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
596 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
597 | GCC_WARN_UNDECLARED_SELECTOR = YES;
598 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
599 | GCC_WARN_UNUSED_FUNCTION = YES;
600 | GCC_WARN_UNUSED_VARIABLE = YES;
601 | IPHONEOS_DEPLOYMENT_TARGET = 8.4;
602 | MTL_ENABLE_DEBUG_INFO = NO;
603 | SDKROOT = iphoneos;
604 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
605 | VALIDATE_PRODUCT = YES;
606 | };
607 | name = Release;
608 | };
609 | 6A0E812C1DD13FAE006B1A61 /* Debug */ = {
610 | isa = XCBuildConfiguration;
611 | baseConfigurationReference = 90F933D5C30B23C93C04943F /* Pods-SwiftyVIPERExample.debug.xcconfig */;
612 | buildSettings = {
613 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
614 | DEVELOPMENT_TEAM = FUC97LYJ62;
615 | INFOPLIST_FILE = SwiftyVIPERExample/Info.plist;
616 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
617 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERExample;
618 | PRODUCT_NAME = "$(TARGET_NAME)";
619 | SWIFT_VERSION = 4.0;
620 | };
621 | name = Debug;
622 | };
623 | 6A0E812D1DD13FAE006B1A61 /* Release */ = {
624 | isa = XCBuildConfiguration;
625 | baseConfigurationReference = 7B62C270AE3AE7163DD700D6 /* Pods-SwiftyVIPERExample.release.xcconfig */;
626 | buildSettings = {
627 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
628 | DEVELOPMENT_TEAM = FUC97LYJ62;
629 | INFOPLIST_FILE = SwiftyVIPERExample/Info.plist;
630 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
631 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERExample;
632 | PRODUCT_NAME = "$(TARGET_NAME)";
633 | SWIFT_VERSION = 4.0;
634 | };
635 | name = Release;
636 | };
637 | 6A0E812F1DD13FAE006B1A61 /* Debug */ = {
638 | isa = XCBuildConfiguration;
639 | baseConfigurationReference = 8F40ACE46DDE6AFE65773867 /* Pods-SwiftyVIPERExampleTests.debug.xcconfig */;
640 | buildSettings = {
641 | BUNDLE_LOADER = "$(TEST_HOST)";
642 | CLANG_ENABLE_MODULES = YES;
643 | DEVELOPMENT_TEAM = FUC97LYJ62;
644 | INFOPLIST_FILE = SwiftyVIPERExampleTests/Info.plist;
645 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
646 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERExampleTests;
647 | PRODUCT_NAME = "$(TARGET_NAME)";
648 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
649 | SWIFT_VERSION = 4.0;
650 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftyVIPERExample.app/SwiftyVIPERExample";
651 | };
652 | name = Debug;
653 | };
654 | 6A0E81301DD13FAE006B1A61 /* Release */ = {
655 | isa = XCBuildConfiguration;
656 | baseConfigurationReference = 7B13EB3C0E109B519EAC7538 /* Pods-SwiftyVIPERExampleTests.release.xcconfig */;
657 | buildSettings = {
658 | BUNDLE_LOADER = "$(TEST_HOST)";
659 | CLANG_ENABLE_MODULES = YES;
660 | DEVELOPMENT_TEAM = FUC97LYJ62;
661 | INFOPLIST_FILE = SwiftyVIPERExampleTests/Info.plist;
662 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
663 | PRODUCT_BUNDLE_IDENTIFIER = com.codeRed.SwiftyVIPERExampleTests;
664 | PRODUCT_NAME = "$(TARGET_NAME)";
665 | SWIFT_VERSION = 4.0;
666 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftyVIPERExample.app/SwiftyVIPERExample";
667 | };
668 | name = Release;
669 | };
670 | /* End XCBuildConfiguration section */
671 |
672 | /* Begin XCConfigurationList section */
673 | 6A0E81091DD13FAE006B1A61 /* Build configuration list for PBXProject "SwiftyVIPERExample" */ = {
674 | isa = XCConfigurationList;
675 | buildConfigurations = (
676 | 6A0E81291DD13FAE006B1A61 /* Debug */,
677 | 6A0E812A1DD13FAE006B1A61 /* Release */,
678 | );
679 | defaultConfigurationIsVisible = 0;
680 | defaultConfigurationName = Release;
681 | };
682 | 6A0E812B1DD13FAE006B1A61 /* Build configuration list for PBXNativeTarget "SwiftyVIPERExample" */ = {
683 | isa = XCConfigurationList;
684 | buildConfigurations = (
685 | 6A0E812C1DD13FAE006B1A61 /* Debug */,
686 | 6A0E812D1DD13FAE006B1A61 /* Release */,
687 | );
688 | defaultConfigurationIsVisible = 0;
689 | defaultConfigurationName = Release;
690 | };
691 | 6A0E812E1DD13FAE006B1A61 /* Build configuration list for PBXNativeTarget "SwiftyVIPERExampleTests" */ = {
692 | isa = XCConfigurationList;
693 | buildConfigurations = (
694 | 6A0E812F1DD13FAE006B1A61 /* Debug */,
695 | 6A0E81301DD13FAE006B1A61 /* Release */,
696 | );
697 | defaultConfigurationIsVisible = 0;
698 | defaultConfigurationName = Release;
699 | };
700 | /* End XCConfigurationList section */
701 | };
702 | rootObject = 6A0E81061DD13FAE006B1A61 /* Project object */;
703 | }
704 |
--------------------------------------------------------------------------------