diff --git a/ios/tutorials/tutorial1-completed/Podfile b/ios/tutorials/tutorial1-completed/Podfile new file mode 100644 index 000000000..6da84fc6d --- /dev/null +++ b/ios/tutorials/tutorial1-completed/Podfile @@ -0,0 +1,10 @@ +platform :ios, '9.0' + +use_frameworks! +inhibit_all_warnings! + +target 'TicTacToe' do + pod 'RIBs', :path => '../../../' + pod 'SnapKit' + +end diff --git a/ios/tutorials/tutorial1-completed/README.md b/ios/tutorials/tutorial1-completed/README.md new file mode 100644 index 000000000..d10ee2ee5 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/README.md @@ -0,0 +1,21 @@ +# RIBs Tutorial 1: Creating a RIB + +This project is the starting point for [tutorial 1](https://github.com/uber/RIBs/wiki/iOS-Tutorial-1) that will get you aquatinted with the RIBs architecture. + +### Getting started + +Install tooling, unless you've done so already: + +``` +/ios/tooling/install-xcode-template.sh +``` + +Then, install pods for the tutorial: + +``` +gem install cocoapods # In case you don't have it +cd /ios/tutorials/tutorial1 +pod install +``` + +Then, open the TicTacToe.xcworkspace that was generated by `pod install` and follow the steps described in [tutorial 1](https://github.com/uber/RIBs/wiki/iOS-Tutorial-1) on the RIBs wiki. diff --git a/ios/tutorials/tutorial1-completed/TicTacToe.xcodeproj/project.pbxproj b/ios/tutorials/tutorial1-completed/TicTacToe.xcodeproj/project.pbxproj new file mode 100644 index 000000000..3022e74c6 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe.xcodeproj/project.pbxproj @@ -0,0 +1,443 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 7EDD59501FA13579005EC8B2 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 7EDD594F1FA13579005EC8B2 /* Default-568h@2x.png */; }; + AEFA38604D7D1E4A08E9A7FA /* Pods_TicTacToe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B99EABB5C8D25341027C05C5 /* Pods_TicTacToe.framework */; }; + E2B964B22862028D000E175C /* LoggedOutRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B964AE2862028D000E175C /* LoggedOutRouter.swift */; }; + E2B964B32862028D000E175C /* LoggedOutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B964AF2862028D000E175C /* LoggedOutViewController.swift */; }; + E2B964B42862028D000E175C /* LoggedOutBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B964B02862028D000E175C /* LoggedOutBuilder.swift */; }; + E2B964B52862028D000E175C /* LoggedOutInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B964B12862028D000E175C /* LoggedOutInteractor.swift */; }; + E9CB1D521F97303800D84847 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D351F972FD500D84847 /* AppDelegate.swift */; }; + E9CB1D531F97305A00D84847 /* AppComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D341F972FD500D84847 /* AppComponent.swift */; }; + E9CB1D611F9730EF00D84847 /* RootBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D371F972FE400D84847 /* RootBuilder.swift */; }; + E9CB1D631F9730EF00D84847 /* RootComponent+LoggedOut.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D391F972FE400D84847 /* RootComponent+LoggedOut.swift */; }; + E9CB1D641F9730EF00D84847 /* RootInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D3A1F972FE400D84847 /* RootInteractor.swift */; }; + E9CB1D651F9730EF00D84847 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D3B1F972FE400D84847 /* RootRouter.swift */; }; + E9CB1D661F9730EF00D84847 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CB1D3C1F972FE400D84847 /* RootViewController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 7EDD594F1FA13579005EC8B2 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 833B15CABE3CBE09720A0409 /* Pods-TicTacToe.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TicTacToe.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TicTacToe/Pods-TicTacToe.debug.xcconfig"; sourceTree = ""; }; + A791EBDAD202886E66137B9C /* Pods-TicTacToe.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TicTacToe.release.xcconfig"; path = "Pods/Target Support Files/Pods-TicTacToe/Pods-TicTacToe.release.xcconfig"; sourceTree = ""; }; + B99EABB5C8D25341027C05C5 /* Pods_TicTacToe.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TicTacToe.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2B964AE2862028D000E175C /* LoggedOutRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutRouter.swift; sourceTree = ""; }; + E2B964AF2862028D000E175C /* LoggedOutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutViewController.swift; sourceTree = ""; }; + E2B964B02862028D000E175C /* LoggedOutBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutBuilder.swift; sourceTree = ""; }; + E2B964B12862028D000E175C /* LoggedOutInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedOutInteractor.swift; sourceTree = ""; }; + E9894B4A1F972CC500688FCB /* TicTacToe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TicTacToe.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E9894B591F972CC500688FCB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E9CB1D341F972FD500D84847 /* AppComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppComponent.swift; sourceTree = ""; }; + E9CB1D351F972FD500D84847 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E9CB1D371F972FE400D84847 /* RootBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootBuilder.swift; sourceTree = ""; }; + E9CB1D391F972FE400D84847 /* RootComponent+LoggedOut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RootComponent+LoggedOut.swift"; sourceTree = ""; }; + E9CB1D3A1F972FE400D84847 /* RootInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootInteractor.swift; sourceTree = ""; }; + E9CB1D3B1F972FE400D84847 /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = ""; }; + E9CB1D3C1F972FE400D84847 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E9894B471F972CC500688FCB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AEFA38604D7D1E4A08E9A7FA /* Pods_TicTacToe.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 59F943336420DE07CA779F6F /* Pods */ = { + isa = PBXGroup; + children = ( + 833B15CABE3CBE09720A0409 /* Pods-TicTacToe.debug.xcconfig */, + A791EBDAD202886E66137B9C /* Pods-TicTacToe.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 7EDD59511FA135E9005EC8B2 /* Resources */ = { + isa = PBXGroup; + children = ( + 7EDD594F1FA13579005EC8B2 /* Default-568h@2x.png */, + ); + path = Resources; + sourceTree = ""; + }; + E9894B411F972CC500688FCB = { + isa = PBXGroup; + children = ( + E9894B4C1F972CC500688FCB /* TicTacToe */, + E9894B4B1F972CC500688FCB /* Products */, + 59F943336420DE07CA779F6F /* Pods */, + F5205CCF508911BE388D8406 /* Frameworks */, + ); + sourceTree = ""; + }; + E9894B4B1F972CC500688FCB /* Products */ = { + isa = PBXGroup; + children = ( + E9894B4A1F972CC500688FCB /* TicTacToe.app */, + ); + name = Products; + sourceTree = ""; + }; + E9894B4C1F972CC500688FCB /* TicTacToe */ = { + isa = PBXGroup; + children = ( + 7EDD59511FA135E9005EC8B2 /* Resources */, + E9CB1D331F972FD500D84847 /* AppStart */, + E9CB1D421F972FE400D84847 /* LoggedOut */, + E9CB1D361F972FE400D84847 /* Root */, + E9894B591F972CC500688FCB /* Info.plist */, + ); + path = TicTacToe; + sourceTree = ""; + }; + E9CB1D331F972FD500D84847 /* AppStart */ = { + isa = PBXGroup; + children = ( + E9CB1D341F972FD500D84847 /* AppComponent.swift */, + E9CB1D351F972FD500D84847 /* AppDelegate.swift */, + ); + path = AppStart; + sourceTree = ""; + }; + E9CB1D361F972FE400D84847 /* Root */ = { + isa = PBXGroup; + children = ( + E9CB1D371F972FE400D84847 /* RootBuilder.swift */, + E9CB1D391F972FE400D84847 /* RootComponent+LoggedOut.swift */, + E9CB1D3A1F972FE400D84847 /* RootInteractor.swift */, + E9CB1D3B1F972FE400D84847 /* RootRouter.swift */, + E9CB1D3C1F972FE400D84847 /* RootViewController.swift */, + ); + path = Root; + sourceTree = ""; + }; + E9CB1D421F972FE400D84847 /* LoggedOut */ = { + isa = PBXGroup; + children = ( + E2B964AE2862028D000E175C /* LoggedOutRouter.swift */, + E2B964AF2862028D000E175C /* LoggedOutViewController.swift */, + E2B964B02862028D000E175C /* LoggedOutBuilder.swift */, + E2B964B12862028D000E175C /* LoggedOutInteractor.swift */, + ); + path = LoggedOut; + sourceTree = ""; + }; + F5205CCF508911BE388D8406 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B99EABB5C8D25341027C05C5 /* Pods_TicTacToe.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E9894B491F972CC500688FCB /* TicTacToe */ = { + isa = PBXNativeTarget; + buildConfigurationList = E9894B671F972CC600688FCB /* Build configuration list for PBXNativeTarget "TicTacToe" */; + buildPhases = ( + 64CF0EF6C16C782FD4AF3F3C /* [CP] Check Pods Manifest.lock */, + E9894B461F972CC500688FCB /* Sources */, + E9894B471F972CC500688FCB /* Frameworks */, + E9894B481F972CC500688FCB /* Resources */, + 01C0219C62DB08840E36B78D /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TicTacToe; + productName = TicTacToe; + productReference = E9894B4A1F972CC500688FCB /* TicTacToe.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E9894B421F972CC500688FCB /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = Uber; + TargetAttributes = { + E9894B491F972CC500688FCB = { + CreatedOnToolsVersion = 9.0; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = E9894B451F972CC500688FCB /* Build configuration list for PBXProject "TicTacToe" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = E9894B411F972CC500688FCB; + productRefGroup = E9894B4B1F972CC500688FCB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E9894B491F972CC500688FCB /* TicTacToe */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + E9894B481F972CC500688FCB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7EDD59501FA13579005EC8B2 /* Default-568h@2x.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 01C0219C62DB08840E36B78D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-TicTacToe/Pods-TicTacToe-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/RIBs/RIBs.framework", + "${BUILT_PRODUCTS_DIR}/RxRelay/RxRelay.framework", + "${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework", + "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RIBs.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRelay.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-TicTacToe/Pods-TicTacToe-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 64CF0EF6C16C782FD4AF3F3C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TicTacToe-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + 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"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E9894B461F972CC500688FCB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E2B964B52862028D000E175C /* LoggedOutInteractor.swift in Sources */, + E9CB1D521F97303800D84847 /* AppDelegate.swift in Sources */, + E9CB1D641F9730EF00D84847 /* RootInteractor.swift in Sources */, + E2B964B42862028D000E175C /* LoggedOutBuilder.swift in Sources */, + E9CB1D631F9730EF00D84847 /* RootComponent+LoggedOut.swift in Sources */, + E2B964B22862028D000E175C /* LoggedOutRouter.swift in Sources */, + E9CB1D611F9730EF00D84847 /* RootBuilder.swift in Sources */, + E9CB1D531F97305A00D84847 /* AppComponent.swift in Sources */, + E9CB1D651F9730EF00D84847 /* RootRouter.swift in Sources */, + E2B964B32862028D000E175C /* LoggedOutViewController.swift in Sources */, + E9CB1D661F9730EF00D84847 /* RootViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + E9894B651F972CC600688FCB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + E9894B661F972CC600688FCB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + E9894B681F972CC600688FCB /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 833B15CABE3CBE09720A0409 /* Pods-TicTacToe.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = TicTacToe/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.ubercab.TicTacToe; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + E9894B691F972CC600688FCB /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A791EBDAD202886E66137B9C /* Pods-TicTacToe.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = TicTacToe/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.ubercab.TicTacToe; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E9894B451F972CC500688FCB /* Build configuration list for PBXProject "TicTacToe" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9894B651F972CC600688FCB /* Debug */, + E9894B661F972CC600688FCB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E9894B671F972CC600688FCB /* Build configuration list for PBXNativeTarget "TicTacToe" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E9894B681F972CC600688FCB /* Debug */, + E9894B691F972CC600688FCB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E9894B421F972CC500688FCB /* Project object */; +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppComponent.swift b/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppComponent.swift new file mode 100644 index 000000000..cc73b41e4 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppComponent.swift @@ -0,0 +1,24 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +class AppComponent: Component, RootDependency { + + init() { + super.init(dependency: EmptyComponent()) + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppDelegate.swift b/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppDelegate.swift new file mode 100644 index 000000000..4d46cd5cd --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/AppStart/AppDelegate.swift @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs +import UIKit + +/// Game app delegate. +@UIApplicationMain +public class AppDelegate: UIResponder, UIApplicationDelegate { + + /// The window. + public var window: UIWindow? + + /// Tells the delegate that the launch process is almost done and the app is almost ready to run. + /// + /// - parameter application: Your singleton app object. + /// - parameter launchOptions: A dictionary indicating the reason the app was launched (if any). The contents of + /// this dictionary may be empty in situations where the user launched the app directly. For information about + /// the possible keys in this dictionary and how to handle them, see Launch Options Keys. + /// - returns: false if the app cannot handle the URL resource or continue a user activity, otherwise return true. + public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + let window = UIWindow(frame: UIScreen.main.bounds) + self.window = window + + let launchRouter = RootBuilder(dependency: AppComponent()).build() + self.launchRouter = launchRouter + launchRouter.launch(from: window) + + return true + } + + // MARK: - Private + + private var launchRouter: LaunchRouting? +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Info.plist b/ios/tutorials/tutorial1-completed/TicTacToe/Info.plist new file mode 100644 index 000000000..cf61db68d --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIcons + + CFBundleIcons~ipad + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutBuilder.swift b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutBuilder.swift new file mode 100644 index 000000000..24f6b0c1e --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutBuilder.swift @@ -0,0 +1,48 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +protocol LoggedOutDependency: Dependency { + // TODO: Declare the set of dependencies required by this RIB, but cannot be + // created by this RIB. +} + +final class LoggedOutComponent: Component { + + // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +} + +// MARK: - Builder + +protocol LoggedOutBuildable: Buildable { + func build(withListener listener: LoggedOutListener) -> LoggedOutRouting +} + +final class LoggedOutBuilder: Builder, LoggedOutBuildable { + + override init(dependency: LoggedOutDependency) { + super.init(dependency: dependency) + } + + func build(withListener listener: LoggedOutListener) -> LoggedOutRouting { + let component = LoggedOutComponent(dependency: dependency) + let viewController = LoggedOutViewController() + let interactor = LoggedOutInteractor(presenter: viewController) + interactor.listener = listener + return LoggedOutRouter(interactor: interactor, viewController: viewController) + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutInteractor.swift b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutInteractor.swift new file mode 100644 index 000000000..a52d73e09 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutInteractor.swift @@ -0,0 +1,69 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs +import RxSwift + +protocol LoggedOutRouting: ViewableRouting { + // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. +} + +protocol LoggedOutPresentable: Presentable { + var listener: LoggedOutPresentableListener? { get set } + // TODO: Declare methods the interactor can invoke the presenter to present data. +} + +protocol LoggedOutListener: AnyObject { + // TODO: Declare methods the interactor can invoke to communicate with other RIBs. +} + +final class LoggedOutInteractor: PresentableInteractor, LoggedOutInteractable, LoggedOutPresentableListener { + + weak var router: LoggedOutRouting? + weak var listener: LoggedOutListener? + + func login(withPlayer1Name player1Name: String?, player2Name: String?) { + let player1NameWithDefault = playerName(player1Name, withDefaultName: "Player 1") + let player2NameWithDefault = playerName(player2Name, withDefaultName: "Player 2") + + print("\(player1NameWithDefault) vs \(player2NameWithDefault)") + } + + private func playerName(_ name: String?, withDefaultName defaultName: String) -> String { + if let name = name { + return name.isEmpty ? defaultName : name + } else { + return defaultName + } + } + + // TODO: Add additional dependencies to constructor. Do not perform any logic + // in constructor. + override init(presenter: LoggedOutPresentable) { + super.init(presenter: presenter) + presenter.listener = self + } + + override func didBecomeActive() { + super.didBecomeActive() + // TODO: Implement business logic here. + } + + override func willResignActive() { + super.willResignActive() + // TODO: Pause any business logic. + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutRouter.swift b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutRouter.swift new file mode 100644 index 000000000..c9cadb437 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutRouter.swift @@ -0,0 +1,35 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +protocol LoggedOutInteractable: Interactable { + var router: LoggedOutRouting? { get set } + var listener: LoggedOutListener? { get set } +} + +protocol LoggedOutViewControllable: ViewControllable { + // TODO: Declare methods the router invokes to manipulate the view hierarchy. +} + +final class LoggedOutRouter: ViewableRouter, LoggedOutRouting { + + // TODO: Constructor inject child builder protocols to allow building children. + override init(interactor: LoggedOutInteractable, viewController: LoggedOutViewControllable) { + super.init(interactor: interactor, viewController: viewController) + interactor.router = self + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutViewController.swift b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutViewController.swift new file mode 100644 index 000000000..57db7103e --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/LoggedOut/LoggedOutViewController.swift @@ -0,0 +1,82 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs +import RxSwift +import UIKit +import SnapKit + +protocol LoggedOutPresentableListener: AnyObject { + func login(withPlayer1Name player1Name: String?, player2Name: String?) +} + +final class LoggedOutViewController: UIViewController, LoggedOutPresentable, LoggedOutViewControllable { + + weak var listener: LoggedOutPresentableListener? + + private var player1Field: UITextField? + private var player2Field: UITextField? + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = UIColor.white + let playerFields = buildPlayerFields() + buildLoginButton(withPlayer1Field: playerFields.player1Field, player2Field: playerFields.player2Field) + } + + private func buildPlayerFields() -> (player1Field: UITextField, player2Field: UITextField) { + let player1Field = UITextField() + self.player1Field = player1Field + player1Field.borderStyle = UITextBorderStyle.line + view.addSubview(player1Field) + player1Field.placeholder = "Player 1 name" + player1Field.snp.makeConstraints { (maker: ConstraintMaker) in + maker.top.equalTo(self.view).offset(100) + maker.leading.trailing.equalTo(self.view).inset(40) + maker.height.equalTo(40) + } + + let player2Field = UITextField() + self.player2Field = player2Field + player2Field.borderStyle = UITextBorderStyle.line + view.addSubview(player2Field) + player2Field.placeholder = "Player 2 name" + player2Field.snp.makeConstraints { (maker: ConstraintMaker) in + maker.top.equalTo(player1Field.snp.bottom).offset(20) + maker.left.right.height.equalTo(player1Field) + } + + return (player1Field, player2Field) + } + + private func buildLoginButton(withPlayer1Field player1Field: UITextField, player2Field: UITextField) { + let loginButton = UIButton() + view.addSubview(loginButton) + loginButton.snp.makeConstraints { (maker: ConstraintMaker) in + maker.top.equalTo(player2Field.snp.bottom).offset(20) + maker.left.right.height.equalTo(player1Field) + } + loginButton.setTitle("Login", for: .normal) + loginButton.setTitleColor(UIColor.white, for: .normal) + loginButton.backgroundColor = UIColor.black + loginButton.addTarget(self, action: #selector(didTapLoginButton), for: .touchUpInside) + } + + @objc private func didTapLoginButton() { + listener?.login(withPlayer1Name: player1Field?.text, player2Name: player2Field?.text) + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Resources/Default-568h@2x.png b/ios/tutorials/tutorial1-completed/TicTacToe/Resources/Default-568h@2x.png new file mode 100644 index 000000000..0891b7aab Binary files /dev/null and b/ios/tutorials/tutorial1-completed/TicTacToe/Resources/Default-568h@2x.png differ diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootBuilder.swift b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootBuilder.swift new file mode 100644 index 000000000..7f2676b24 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootBuilder.swift @@ -0,0 +1,51 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +protocol RootDependency: Dependency { + // TODO: Declare the set of dependencies required by this RIB, but cannot be + // created by this RIB. +} + +final class RootComponent: Component { + + // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +} + +// MARK: - Builder + +protocol RootBuildable: Buildable { + func build() -> LaunchRouting +} + +final class RootBuilder: Builder, RootBuildable { + + override init(dependency: RootDependency) { + super.init(dependency: dependency) + } + + func build() -> LaunchRouting { + let component = RootComponent(dependency: dependency) + let viewController = RootViewController() + let interactor = RootInteractor(presenter: viewController) + + let loggedOutBuilder = LoggedOutBuilder(dependency: component) + return RootRouter(interactor: interactor, + viewController: viewController, + loggedOutBuilder: loggedOutBuilder) + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootComponent+LoggedOut.swift b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootComponent+LoggedOut.swift new file mode 100644 index 000000000..a2f32f599 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootComponent+LoggedOut.swift @@ -0,0 +1,30 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +/// The dependencies needed from the parent scope of Root to provide for the LoggedOut scope. +// TODO: Update RootDependency protocol to inherit this protocol. +protocol RootDependencyLoggedOut: Dependency { + + // TODO: Declare dependencies needed from the parent scope of Root to provide dependencies + // for the LoggedOut scope. +} + +extension RootComponent: LoggedOutDependency { + + // TODO: Implement properties to provide for LoggedOut scope. +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootInteractor.swift b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootInteractor.swift new file mode 100644 index 000000000..a1ec1902a --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootInteractor.swift @@ -0,0 +1,55 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs +import RxSwift + +protocol RootRouting: ViewableRouting { + // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. +} + +protocol RootPresentable: Presentable { + var listener: RootPresentableListener? { get set } + // TODO: Declare methods the interactor can invoke the presenter to present data. +} + +protocol RootListener: AnyObject { + // TODO: Declare methods the interactor can invoke to communicate with other RIBs. +} + +final class RootInteractor: PresentableInteractor, RootInteractable, RootPresentableListener { + + weak var router: RootRouting? + + weak var listener: RootListener? + + // TODO: Add additional dependencies to constructor. Do not perform any logic + // in constructor. + override init(presenter: RootPresentable) { + super.init(presenter: presenter) + presenter.listener = self + } + + override func didBecomeActive() { + super.didBecomeActive() + // TODO: Implement business logic here. + } + + override func willResignActive() { + super.willResignActive() + // TODO: Pause any business logic. + } +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootRouter.swift b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootRouter.swift new file mode 100644 index 000000000..9e6415832 --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootRouter.swift @@ -0,0 +1,52 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs + +protocol RootInteractable: Interactable, LoggedOutListener { + var router: RootRouting? { get set } + var listener: RootListener? { get set } +} + +protocol RootViewControllable: ViewControllable { + func present(viewController: ViewControllable) +} + +final class RootRouter: LaunchRouter, RootRouting { + + init(interactor: RootInteractable, + viewController: RootViewControllable, + loggedOutBuilder: LoggedOutBuildable) { + self.loggedOutBuilder = loggedOutBuilder + super.init(interactor: interactor, viewController: viewController) + interactor.router = self + } + + override func didLoad() { + super.didLoad() + + let loggedOut = loggedOutBuilder.build(withListener: interactor) + self.loggedOut = loggedOut + attachChild(loggedOut) + viewController.present(viewController: loggedOut.viewControllable) + } + + // MARK: - Private + + private let loggedOutBuilder: LoggedOutBuildable + + private var loggedOut: ViewableRouting? +} diff --git a/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootViewController.swift b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootViewController.swift new file mode 100644 index 000000000..06cdc492c --- /dev/null +++ b/ios/tutorials/tutorial1-completed/TicTacToe/Root/RootViewController.swift @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017. Uber Technologies +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import RIBs +import SnapKit +import UIKit + +protocol RootPresentableListener: AnyObject { + // TODO: Declare properties and methods that the view controller can invoke to perform + // business logic, such as signIn(). This protocol is implemented by the corresponding + // interactor class. +} + +final class RootViewController: UIViewController, RootPresentable, RootViewControllable { + + weak var listener: RootPresentableListener? + + init() { + super.init(nibName: nil, bundle: nil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("Method is not supported") + } + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = UIColor.white + } + + // MARK: - RootViewControllable + + func present(viewController: ViewControllable) { + present(viewController.uiviewController, animated: true, completion: nil) + } +}