├── .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 | ![Choice](Assets/Template Choice.png) 130 | 131 | Next, choose the Module name. We'll go with `Custom`. 132 | 133 | ![Name](Assets/Template Name.png) 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 | --------------------------------------------------------------------------------