├── .gitignore ├── Podfile ├── README.md ├── iOSModuleArchitecture.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── iOSModuleArchitecture.xcworkspace └── contents.xcworkspacedata ├── iOSModuleArchitecture ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Code │ ├── Common │ │ ├── AppDelegate.swift │ │ └── RootWireframe.swift │ ├── Modules │ │ ├── FirstModule │ │ │ ├── Application Logic │ │ │ │ ├── Datastore │ │ │ │ │ ├── FirstModuleDatastore.swift │ │ │ │ │ ├── LocalDatastore │ │ │ │ │ │ ├── FirstModuleLocalStorageDatastore.swift │ │ │ │ │ │ └── IFirstModuleLocalDatastore.swift │ │ │ │ │ └── RemoteDatastore │ │ │ │ │ │ ├── FirstModuleWebServiceDatastore.swift │ │ │ │ │ │ └── IFirstModuleRemoteDatastore.swift │ │ │ │ ├── Interactor │ │ │ │ │ ├── FirstModuleInteractor.swift │ │ │ │ │ └── FirstModuleInteractorIO.swift │ │ │ │ └── Model │ │ │ │ │ └── FirstModuleModel.swift │ │ │ ├── Factory │ │ │ │ ├── FirstModuleBuilder.swift │ │ │ │ └── IFirstModuleBuilder.swift │ │ │ ├── IO │ │ │ │ ├── FirstModuleIO.swift │ │ │ │ └── IFirstModuleIO.swift │ │ │ └── User Interface │ │ │ │ ├── Presenter │ │ │ │ └── FirstModulePresenter.swift │ │ │ │ ├── View │ │ │ │ ├── FirstModuleViewController.swift │ │ │ │ └── IFirstModuleView.swift │ │ │ │ └── Wireframe │ │ │ │ └── FirstModuleWireframe.swift │ │ └── SecondModule │ │ │ ├── Factory │ │ │ ├── ISecondModuleBuilder.swift │ │ │ └── SecondModuleBuilder.swift │ │ │ ├── IO │ │ │ ├── ISecondModuleIO.swift │ │ │ └── SecondModuleIO.swift │ │ │ └── User Interface │ │ │ ├── Presenter │ │ │ └── SecondModulePresenter.swift │ │ │ ├── View │ │ │ ├── ISecondModuleView.swift │ │ │ └── SecondModuleViewController.swift │ │ │ └── Wireframe │ │ │ └── SecondModuleWireframe.swift │ └── iOSModuleArchitecture-Bridging-Header.h ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── ViewController.swift └── iOSModuleArchitectureTests ├── Info.plist └── iOSModuleArchitectureTests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | 23 | *.lock 24 | 25 | PassingData class diagram.graffle 26 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '7.0' 2 | 3 | pod 'JLRoutes' 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOSModuleArchitecture 2 | 3 | Questions and feedbacks are welcomed in the *issues* part of the repository! 4 | 5 | ## Introduction 6 | 7 | Quick example of how divide an app into modules to respect the [SOLID](http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29) principles based on the [VIPER architecture](http://www.objc.io/issue-13/viper.html). 8 | 9 | In this application, there are two modules. The first one retrieve a model which contains a string from the (fake) remote data store in order to send the string and display it in the second module. 10 | 11 | 12 | ## How to start the app 13 | 14 | After downloading the repository, be sure that you already installed [CocoaPods](https://cocoapods.org/) and run the command `pod install` in the directory of the repository through a terminal. Then open the file named **iOSModuleArchitecture.xcworkspace**. 15 | 16 | ## Architecture 17 | 18 | - **Builder**: Builder design pattern in charge of the instantiation of the whole module. 19 | - **IO**: Class that manage the input and the output of the module. 20 | - **Wireframe**: Manages the instantiation of the view inside the window. 21 | - **ViewController**: The ViewController displays the UI elements and sends the user interaction to the Presenter. 22 | - **Presenter:** Mediator design pattern that drive the interactions between the ViewController, the Interactor and the IO. This class drives the user interaction depending on the type of action. (business logic or the changing of module) 23 | - **Interactor:** Manages all the business logic of the module and handles the call to the Datastore to store and retrieve objects. 24 | - **Datastore:** Communicates with the local storage and the remote storage by using the strategy design pattern. 25 | - **Model:** Simply the data that will be transferred in the module. 26 | 27 | ## Class diagram 28 | *This class diagram represents the modelization of the main module - FirstModule - of this app* 29 | 30 | ![class diagram](http://s14.postimg.org/g7de4nxsh/Passing_Data_class_diagram.png) 31 | 32 | As you can see with the `stereotypes` on the class diagram there are different design patterns used in this module: 33 | - [Builder](https://sourcemaking.com/design_patterns/builder) 34 | - [Facade] (https://sourcemaking.com/design_patterns/facade) 35 | - [Mediator] (https://sourcemaking.com/design_patterns/mediator) 36 | - [Strategy] (https://sourcemaking.com/design_patterns/strategy) 37 | 38 | ## FAQ 39 | 40 | **Q: Isn't it overkill such a decomposition?** 41 | A: I took the habit to always decompose the features of an app in modules. The decomposition shown in this repository is an example of a complete decomposition that respects SOLID principles. Feel free to adapt it to your project's requirements. Such an implementation permits to the modules to be interchangeable, highly scalable and highly abstracted. If you're afraid that you will take too much time to implement a whole app using this architecture keep in mind two facts. Firstly, you can create tools to automate the creation of module with all the boilerplate code. And you will loose less time to take the time to think to a *good-enough* architecture rather than program a cheap one and rewrite a lot of code when the first version of the project starts to be unmanageable. 42 | 43 | **Q: How can I transfer objects from one module to another?** 44 | A: CoreData is the perfect tool for this. Send the string entity id of the stored object to your second module, then retrieve the object from core data using the entity id. 45 | 46 | -------------------------------------------------------------------------------- /iOSModuleArchitecture.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4D54C47B1AE9CF9200AF7477 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4D54C4791AE9CF9200AF7477 /* Main.storyboard */; }; 11 | 4D54C47D1AE9CF9200AF7477 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4D54C47C1AE9CF9200AF7477 /* Images.xcassets */; }; 12 | 4D54C4801AE9CF9200AF7477 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4D54C47E1AE9CF9200AF7477 /* LaunchScreen.xib */; }; 13 | 4D54C48C1AE9CF9200AF7477 /* iOSModuleArchitectureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C48B1AE9CF9200AF7477 /* iOSModuleArchitectureTests.swift */; }; 14 | 4D54C4B81AE9CFAA00AF7477 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4971AE9CFAA00AF7477 /* AppDelegate.swift */; }; 15 | 4D54C4B91AE9CFAA00AF7477 /* RootWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4981AE9CFAA00AF7477 /* RootWireframe.swift */; }; 16 | 4D54C4BA1AE9CFAA00AF7477 /* FirstModuleDatastore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C49E1AE9CFAA00AF7477 /* FirstModuleDatastore.swift */; }; 17 | 4D54C4BB1AE9CFAA00AF7477 /* FirstModuleLocalStorageDatastore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A01AE9CFAA00AF7477 /* FirstModuleLocalStorageDatastore.swift */; }; 18 | 4D54C4BC1AE9CFAA00AF7477 /* IFirstModuleLocalDatastore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A11AE9CFAA00AF7477 /* IFirstModuleLocalDatastore.swift */; }; 19 | 4D54C4BD1AE9CFAA00AF7477 /* FirstModuleWebServiceDatastore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A31AE9CFAA00AF7477 /* FirstModuleWebServiceDatastore.swift */; }; 20 | 4D54C4BE1AE9CFAA00AF7477 /* IFirstModuleRemoteDatastore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A41AE9CFAA00AF7477 /* IFirstModuleRemoteDatastore.swift */; }; 21 | 4D54C4BF1AE9CFAA00AF7477 /* FirstModuleInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A61AE9CFAA00AF7477 /* FirstModuleInteractor.swift */; }; 22 | 4D54C4C01AE9CFAA00AF7477 /* FirstModuleInteractorIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A71AE9CFAA00AF7477 /* FirstModuleInteractorIO.swift */; }; 23 | 4D54C4C11AE9CFAA00AF7477 /* FirstModuleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4A91AE9CFAA00AF7477 /* FirstModuleModel.swift */; }; 24 | 4D54C4C21AE9CFAA00AF7477 /* FirstModuleBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4AB1AE9CFAA00AF7477 /* FirstModuleBuilder.swift */; }; 25 | 4D54C4C31AE9CFAA00AF7477 /* IFirstModuleBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4AC1AE9CFAA00AF7477 /* IFirstModuleBuilder.swift */; }; 26 | 4D54C4C41AE9CFAA00AF7477 /* FirstModuleIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4AE1AE9CFAA00AF7477 /* FirstModuleIO.swift */; }; 27 | 4D54C4C51AE9CFAA00AF7477 /* IFirstModuleIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4AF1AE9CFAA00AF7477 /* IFirstModuleIO.swift */; }; 28 | 4D54C4C61AE9CFAA00AF7477 /* FirstModulePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4B21AE9CFAA00AF7477 /* FirstModulePresenter.swift */; }; 29 | 4D54C4C71AE9CFAA00AF7477 /* FirstModuleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4B41AE9CFAA00AF7477 /* FirstModuleViewController.swift */; }; 30 | 4D54C4C81AE9CFAA00AF7477 /* IFirstModuleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4B51AE9CFAA00AF7477 /* IFirstModuleView.swift */; }; 31 | 4D54C4C91AE9CFAA00AF7477 /* FirstModuleWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D54C4B71AE9CFAA00AF7477 /* FirstModuleWireframe.swift */; }; 32 | 4DC58D4E1AE9FA4C00C6A015 /* ISecondModuleBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D391AE9FA4C00C6A015 /* ISecondModuleBuilder.swift */; }; 33 | 4DC58D4F1AE9FA4C00C6A015 /* SecondModuleBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D3A1AE9FA4C00C6A015 /* SecondModuleBuilder.swift */; }; 34 | 4DC58D501AE9FA4C00C6A015 /* ISecondModuleIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D3C1AE9FA4C00C6A015 /* ISecondModuleIO.swift */; }; 35 | 4DC58D511AE9FA4C00C6A015 /* SecondModuleIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D3D1AE9FA4C00C6A015 /* SecondModuleIO.swift */; }; 36 | 4DC58D521AE9FA4C00C6A015 /* SecondModulePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D401AE9FA4C00C6A015 /* SecondModulePresenter.swift */; }; 37 | 4DC58D531AE9FA4C00C6A015 /* ISecondModuleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D421AE9FA4C00C6A015 /* ISecondModuleView.swift */; }; 38 | 4DC58D541AE9FA4C00C6A015 /* SecondModuleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D431AE9FA4C00C6A015 /* SecondModuleViewController.swift */; }; 39 | 4DC58D551AE9FA4C00C6A015 /* SecondModuleWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC58D451AE9FA4C00C6A015 /* SecondModuleWireframe.swift */; }; 40 | A208E5E3124582209E952F50 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6BB6040790C5D79B47381A9 /* libPods.a */; }; 41 | /* End PBXBuildFile section */ 42 | 43 | /* Begin PBXContainerItemProxy section */ 44 | 4D54C4861AE9CF9200AF7477 /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = 4D54C4681AE9CF9200AF7477 /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = 4D54C46F1AE9CF9200AF7477; 49 | remoteInfo = iOSModuleArchitecture; 50 | }; 51 | /* End PBXContainerItemProxy section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 042C63B78896715096D47E28 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 55 | 4D54C4701AE9CF9200AF7477 /* iOSModuleArchitecture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSModuleArchitecture.app; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 4D54C4741AE9CF9200AF7477 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 4D54C47A1AE9CF9200AF7477 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 58 | 4D54C47C1AE9CF9200AF7477 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 59 | 4D54C47F1AE9CF9200AF7477 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 60 | 4D54C4851AE9CF9200AF7477 /* iOSModuleArchitectureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSModuleArchitectureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 4D54C48A1AE9CF9200AF7477 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | 4D54C48B1AE9CF9200AF7477 /* iOSModuleArchitectureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSModuleArchitectureTests.swift; sourceTree = ""; }; 63 | 4D54C4971AE9CFAA00AF7477 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 64 | 4D54C4981AE9CFAA00AF7477 /* RootWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootWireframe.swift; sourceTree = ""; }; 65 | 4D54C4991AE9CFAA00AF7477 /* iOSModuleArchitecture-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "iOSModuleArchitecture-Bridging-Header.h"; sourceTree = ""; }; 66 | 4D54C49E1AE9CFAA00AF7477 /* FirstModuleDatastore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleDatastore.swift; sourceTree = ""; }; 67 | 4D54C4A01AE9CFAA00AF7477 /* FirstModuleLocalStorageDatastore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleLocalStorageDatastore.swift; sourceTree = ""; }; 68 | 4D54C4A11AE9CFAA00AF7477 /* IFirstModuleLocalDatastore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IFirstModuleLocalDatastore.swift; sourceTree = ""; }; 69 | 4D54C4A31AE9CFAA00AF7477 /* FirstModuleWebServiceDatastore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleWebServiceDatastore.swift; sourceTree = ""; }; 70 | 4D54C4A41AE9CFAA00AF7477 /* IFirstModuleRemoteDatastore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IFirstModuleRemoteDatastore.swift; sourceTree = ""; }; 71 | 4D54C4A61AE9CFAA00AF7477 /* FirstModuleInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleInteractor.swift; sourceTree = ""; }; 72 | 4D54C4A71AE9CFAA00AF7477 /* FirstModuleInteractorIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleInteractorIO.swift; sourceTree = ""; }; 73 | 4D54C4A91AE9CFAA00AF7477 /* FirstModuleModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleModel.swift; sourceTree = ""; }; 74 | 4D54C4AB1AE9CFAA00AF7477 /* FirstModuleBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleBuilder.swift; sourceTree = ""; }; 75 | 4D54C4AC1AE9CFAA00AF7477 /* IFirstModuleBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IFirstModuleBuilder.swift; sourceTree = ""; }; 76 | 4D54C4AE1AE9CFAA00AF7477 /* FirstModuleIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleIO.swift; sourceTree = ""; }; 77 | 4D54C4AF1AE9CFAA00AF7477 /* IFirstModuleIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IFirstModuleIO.swift; sourceTree = ""; }; 78 | 4D54C4B21AE9CFAA00AF7477 /* FirstModulePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModulePresenter.swift; sourceTree = ""; }; 79 | 4D54C4B41AE9CFAA00AF7477 /* FirstModuleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleViewController.swift; sourceTree = ""; }; 80 | 4D54C4B51AE9CFAA00AF7477 /* IFirstModuleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IFirstModuleView.swift; sourceTree = ""; }; 81 | 4D54C4B71AE9CFAA00AF7477 /* FirstModuleWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstModuleWireframe.swift; sourceTree = ""; }; 82 | 4DC58D391AE9FA4C00C6A015 /* ISecondModuleBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISecondModuleBuilder.swift; sourceTree = ""; }; 83 | 4DC58D3A1AE9FA4C00C6A015 /* SecondModuleBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondModuleBuilder.swift; sourceTree = ""; }; 84 | 4DC58D3C1AE9FA4C00C6A015 /* ISecondModuleIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISecondModuleIO.swift; sourceTree = ""; }; 85 | 4DC58D3D1AE9FA4C00C6A015 /* SecondModuleIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondModuleIO.swift; sourceTree = ""; }; 86 | 4DC58D401AE9FA4C00C6A015 /* SecondModulePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondModulePresenter.swift; sourceTree = ""; }; 87 | 4DC58D421AE9FA4C00C6A015 /* ISecondModuleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISecondModuleView.swift; sourceTree = ""; }; 88 | 4DC58D431AE9FA4C00C6A015 /* SecondModuleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondModuleViewController.swift; sourceTree = ""; }; 89 | 4DC58D451AE9FA4C00C6A015 /* SecondModuleWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondModuleWireframe.swift; sourceTree = ""; }; 90 | B6BB6040790C5D79B47381A9 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | DBF2111F7C7CD118CA868498 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 92 | /* End PBXFileReference section */ 93 | 94 | /* Begin PBXFrameworksBuildPhase section */ 95 | 4D54C46D1AE9CF9200AF7477 /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | A208E5E3124582209E952F50 /* libPods.a in Frameworks */, 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | 4D54C4821AE9CF9200AF7477 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | /* End PBXFrameworksBuildPhase section */ 111 | 112 | /* Begin PBXGroup section */ 113 | 2EF3963C7EDA37CB9A077C28 /* Pods */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 042C63B78896715096D47E28 /* Pods.debug.xcconfig */, 117 | DBF2111F7C7CD118CA868498 /* Pods.release.xcconfig */, 118 | ); 119 | name = Pods; 120 | sourceTree = ""; 121 | }; 122 | 4D54C4671AE9CF9200AF7477 = { 123 | isa = PBXGroup; 124 | children = ( 125 | 4D54C4721AE9CF9200AF7477 /* iOSModuleArchitecture */, 126 | 4D54C4881AE9CF9200AF7477 /* iOSModuleArchitectureTests */, 127 | 4D54C4711AE9CF9200AF7477 /* Products */, 128 | 2EF3963C7EDA37CB9A077C28 /* Pods */, 129 | 4E8F2636A508FFD1CFA27565 /* Frameworks */, 130 | ); 131 | sourceTree = ""; 132 | }; 133 | 4D54C4711AE9CF9200AF7477 /* Products */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 4D54C4701AE9CF9200AF7477 /* iOSModuleArchitecture.app */, 137 | 4D54C4851AE9CF9200AF7477 /* iOSModuleArchitectureTests.xctest */, 138 | ); 139 | name = Products; 140 | sourceTree = ""; 141 | }; 142 | 4D54C4721AE9CF9200AF7477 /* iOSModuleArchitecture */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 4D54C4951AE9CFAA00AF7477 /* Code */, 146 | 4D54C4791AE9CF9200AF7477 /* Main.storyboard */, 147 | 4D54C47C1AE9CF9200AF7477 /* Images.xcassets */, 148 | 4D54C47E1AE9CF9200AF7477 /* LaunchScreen.xib */, 149 | 4D54C4731AE9CF9200AF7477 /* Supporting Files */, 150 | ); 151 | path = iOSModuleArchitecture; 152 | sourceTree = ""; 153 | }; 154 | 4D54C4731AE9CF9200AF7477 /* Supporting Files */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 4D54C4741AE9CF9200AF7477 /* Info.plist */, 158 | ); 159 | name = "Supporting Files"; 160 | sourceTree = ""; 161 | }; 162 | 4D54C4881AE9CF9200AF7477 /* iOSModuleArchitectureTests */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 4D54C48B1AE9CF9200AF7477 /* iOSModuleArchitectureTests.swift */, 166 | 4D54C4891AE9CF9200AF7477 /* Supporting Files */, 167 | ); 168 | path = iOSModuleArchitectureTests; 169 | sourceTree = ""; 170 | }; 171 | 4D54C4891AE9CF9200AF7477 /* Supporting Files */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 4D54C48A1AE9CF9200AF7477 /* Info.plist */, 175 | ); 176 | name = "Supporting Files"; 177 | sourceTree = ""; 178 | }; 179 | 4D54C4951AE9CFAA00AF7477 /* Code */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 4D54C4961AE9CFAA00AF7477 /* Common */, 183 | 4D54C4991AE9CFAA00AF7477 /* iOSModuleArchitecture-Bridging-Header.h */, 184 | 4D54C49A1AE9CFAA00AF7477 /* Modules */, 185 | ); 186 | path = Code; 187 | sourceTree = ""; 188 | }; 189 | 4D54C4961AE9CFAA00AF7477 /* Common */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 4D54C4971AE9CFAA00AF7477 /* AppDelegate.swift */, 193 | 4D54C4981AE9CFAA00AF7477 /* RootWireframe.swift */, 194 | ); 195 | path = Common; 196 | sourceTree = ""; 197 | }; 198 | 4D54C49A1AE9CFAA00AF7477 /* Modules */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | 4D54C49B1AE9CFAA00AF7477 /* FirstModule */, 202 | 4DC58D291AE9FA4B00C6A015 /* SecondModule */, 203 | ); 204 | path = Modules; 205 | sourceTree = ""; 206 | }; 207 | 4D54C49B1AE9CFAA00AF7477 /* FirstModule */ = { 208 | isa = PBXGroup; 209 | children = ( 210 | 4D54C49C1AE9CFAA00AF7477 /* Application Logic */, 211 | 4D54C4AA1AE9CFAA00AF7477 /* Factory */, 212 | 4D54C4AD1AE9CFAA00AF7477 /* IO */, 213 | 4D54C4B01AE9CFAA00AF7477 /* User Interface */, 214 | ); 215 | path = FirstModule; 216 | sourceTree = ""; 217 | }; 218 | 4D54C49C1AE9CFAA00AF7477 /* Application Logic */ = { 219 | isa = PBXGroup; 220 | children = ( 221 | 4D54C49D1AE9CFAA00AF7477 /* Datastore */, 222 | 4D54C4A51AE9CFAA00AF7477 /* Interactor */, 223 | 4D54C4A81AE9CFAA00AF7477 /* Model */, 224 | ); 225 | path = "Application Logic"; 226 | sourceTree = ""; 227 | }; 228 | 4D54C49D1AE9CFAA00AF7477 /* Datastore */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | 4D54C49E1AE9CFAA00AF7477 /* FirstModuleDatastore.swift */, 232 | 4D54C49F1AE9CFAA00AF7477 /* LocalDatastore */, 233 | 4D54C4A21AE9CFAA00AF7477 /* RemoteDatastore */, 234 | ); 235 | path = Datastore; 236 | sourceTree = ""; 237 | }; 238 | 4D54C49F1AE9CFAA00AF7477 /* LocalDatastore */ = { 239 | isa = PBXGroup; 240 | children = ( 241 | 4D54C4A01AE9CFAA00AF7477 /* FirstModuleLocalStorageDatastore.swift */, 242 | 4D54C4A11AE9CFAA00AF7477 /* IFirstModuleLocalDatastore.swift */, 243 | ); 244 | path = LocalDatastore; 245 | sourceTree = ""; 246 | }; 247 | 4D54C4A21AE9CFAA00AF7477 /* RemoteDatastore */ = { 248 | isa = PBXGroup; 249 | children = ( 250 | 4D54C4A31AE9CFAA00AF7477 /* FirstModuleWebServiceDatastore.swift */, 251 | 4D54C4A41AE9CFAA00AF7477 /* IFirstModuleRemoteDatastore.swift */, 252 | ); 253 | path = RemoteDatastore; 254 | sourceTree = ""; 255 | }; 256 | 4D54C4A51AE9CFAA00AF7477 /* Interactor */ = { 257 | isa = PBXGroup; 258 | children = ( 259 | 4D54C4A61AE9CFAA00AF7477 /* FirstModuleInteractor.swift */, 260 | 4D54C4A71AE9CFAA00AF7477 /* FirstModuleInteractorIO.swift */, 261 | ); 262 | path = Interactor; 263 | sourceTree = ""; 264 | }; 265 | 4D54C4A81AE9CFAA00AF7477 /* Model */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | 4D54C4A91AE9CFAA00AF7477 /* FirstModuleModel.swift */, 269 | ); 270 | path = Model; 271 | sourceTree = ""; 272 | }; 273 | 4D54C4AA1AE9CFAA00AF7477 /* Factory */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | 4D54C4AB1AE9CFAA00AF7477 /* FirstModuleBuilder.swift */, 277 | 4D54C4AC1AE9CFAA00AF7477 /* IFirstModuleBuilder.swift */, 278 | ); 279 | path = Factory; 280 | sourceTree = ""; 281 | }; 282 | 4D54C4AD1AE9CFAA00AF7477 /* IO */ = { 283 | isa = PBXGroup; 284 | children = ( 285 | 4D54C4AE1AE9CFAA00AF7477 /* FirstModuleIO.swift */, 286 | 4D54C4AF1AE9CFAA00AF7477 /* IFirstModuleIO.swift */, 287 | ); 288 | path = IO; 289 | sourceTree = ""; 290 | }; 291 | 4D54C4B01AE9CFAA00AF7477 /* User Interface */ = { 292 | isa = PBXGroup; 293 | children = ( 294 | 4D54C4B11AE9CFAA00AF7477 /* Presenter */, 295 | 4D54C4B31AE9CFAA00AF7477 /* View */, 296 | 4D54C4B61AE9CFAA00AF7477 /* Wireframe */, 297 | ); 298 | path = "User Interface"; 299 | sourceTree = ""; 300 | }; 301 | 4D54C4B11AE9CFAA00AF7477 /* Presenter */ = { 302 | isa = PBXGroup; 303 | children = ( 304 | 4D54C4B21AE9CFAA00AF7477 /* FirstModulePresenter.swift */, 305 | ); 306 | path = Presenter; 307 | sourceTree = ""; 308 | }; 309 | 4D54C4B31AE9CFAA00AF7477 /* View */ = { 310 | isa = PBXGroup; 311 | children = ( 312 | 4D54C4B41AE9CFAA00AF7477 /* FirstModuleViewController.swift */, 313 | 4D54C4B51AE9CFAA00AF7477 /* IFirstModuleView.swift */, 314 | ); 315 | path = View; 316 | sourceTree = ""; 317 | }; 318 | 4D54C4B61AE9CFAA00AF7477 /* Wireframe */ = { 319 | isa = PBXGroup; 320 | children = ( 321 | 4D54C4B71AE9CFAA00AF7477 /* FirstModuleWireframe.swift */, 322 | ); 323 | path = Wireframe; 324 | sourceTree = ""; 325 | }; 326 | 4DC58D291AE9FA4B00C6A015 /* SecondModule */ = { 327 | isa = PBXGroup; 328 | children = ( 329 | 4DC58D381AE9FA4C00C6A015 /* Factory */, 330 | 4DC58D3B1AE9FA4C00C6A015 /* IO */, 331 | 4DC58D3E1AE9FA4C00C6A015 /* User Interface */, 332 | ); 333 | path = SecondModule; 334 | sourceTree = ""; 335 | }; 336 | 4DC58D381AE9FA4C00C6A015 /* Factory */ = { 337 | isa = PBXGroup; 338 | children = ( 339 | 4DC58D391AE9FA4C00C6A015 /* ISecondModuleBuilder.swift */, 340 | 4DC58D3A1AE9FA4C00C6A015 /* SecondModuleBuilder.swift */, 341 | ); 342 | path = Factory; 343 | sourceTree = ""; 344 | }; 345 | 4DC58D3B1AE9FA4C00C6A015 /* IO */ = { 346 | isa = PBXGroup; 347 | children = ( 348 | 4DC58D3C1AE9FA4C00C6A015 /* ISecondModuleIO.swift */, 349 | 4DC58D3D1AE9FA4C00C6A015 /* SecondModuleIO.swift */, 350 | ); 351 | path = IO; 352 | sourceTree = ""; 353 | }; 354 | 4DC58D3E1AE9FA4C00C6A015 /* User Interface */ = { 355 | isa = PBXGroup; 356 | children = ( 357 | 4DC58D3F1AE9FA4C00C6A015 /* Presenter */, 358 | 4DC58D411AE9FA4C00C6A015 /* View */, 359 | 4DC58D441AE9FA4C00C6A015 /* Wireframe */, 360 | ); 361 | path = "User Interface"; 362 | sourceTree = ""; 363 | }; 364 | 4DC58D3F1AE9FA4C00C6A015 /* Presenter */ = { 365 | isa = PBXGroup; 366 | children = ( 367 | 4DC58D401AE9FA4C00C6A015 /* SecondModulePresenter.swift */, 368 | ); 369 | path = Presenter; 370 | sourceTree = ""; 371 | }; 372 | 4DC58D411AE9FA4C00C6A015 /* View */ = { 373 | isa = PBXGroup; 374 | children = ( 375 | 4DC58D421AE9FA4C00C6A015 /* ISecondModuleView.swift */, 376 | 4DC58D431AE9FA4C00C6A015 /* SecondModuleViewController.swift */, 377 | ); 378 | path = View; 379 | sourceTree = ""; 380 | }; 381 | 4DC58D441AE9FA4C00C6A015 /* Wireframe */ = { 382 | isa = PBXGroup; 383 | children = ( 384 | 4DC58D451AE9FA4C00C6A015 /* SecondModuleWireframe.swift */, 385 | ); 386 | path = Wireframe; 387 | sourceTree = ""; 388 | }; 389 | 4E8F2636A508FFD1CFA27565 /* Frameworks */ = { 390 | isa = PBXGroup; 391 | children = ( 392 | B6BB6040790C5D79B47381A9 /* libPods.a */, 393 | ); 394 | name = Frameworks; 395 | sourceTree = ""; 396 | }; 397 | /* End PBXGroup section */ 398 | 399 | /* Begin PBXNativeTarget section */ 400 | 4D54C46F1AE9CF9200AF7477 /* iOSModuleArchitecture */ = { 401 | isa = PBXNativeTarget; 402 | buildConfigurationList = 4D54C48F1AE9CF9200AF7477 /* Build configuration list for PBXNativeTarget "iOSModuleArchitecture" */; 403 | buildPhases = ( 404 | 2E979EF55A9B38DCDD7AA24A /* Check Pods Manifest.lock */, 405 | 4D54C46C1AE9CF9200AF7477 /* Sources */, 406 | 4D54C46D1AE9CF9200AF7477 /* Frameworks */, 407 | 4D54C46E1AE9CF9200AF7477 /* Resources */, 408 | D7BE4C6E28EF0F1373CDF8D8 /* Copy Pods Resources */, 409 | ); 410 | buildRules = ( 411 | ); 412 | dependencies = ( 413 | ); 414 | name = iOSModuleArchitecture; 415 | productName = iOSModuleArchitecture; 416 | productReference = 4D54C4701AE9CF9200AF7477 /* iOSModuleArchitecture.app */; 417 | productType = "com.apple.product-type.application"; 418 | }; 419 | 4D54C4841AE9CF9200AF7477 /* iOSModuleArchitectureTests */ = { 420 | isa = PBXNativeTarget; 421 | buildConfigurationList = 4D54C4921AE9CF9200AF7477 /* Build configuration list for PBXNativeTarget "iOSModuleArchitectureTests" */; 422 | buildPhases = ( 423 | 4D54C4811AE9CF9200AF7477 /* Sources */, 424 | 4D54C4821AE9CF9200AF7477 /* Frameworks */, 425 | 4D54C4831AE9CF9200AF7477 /* Resources */, 426 | ); 427 | buildRules = ( 428 | ); 429 | dependencies = ( 430 | 4D54C4871AE9CF9200AF7477 /* PBXTargetDependency */, 431 | ); 432 | name = iOSModuleArchitectureTests; 433 | productName = iOSModuleArchitectureTests; 434 | productReference = 4D54C4851AE9CF9200AF7477 /* iOSModuleArchitectureTests.xctest */; 435 | productType = "com.apple.product-type.bundle.unit-test"; 436 | }; 437 | /* End PBXNativeTarget section */ 438 | 439 | /* Begin PBXProject section */ 440 | 4D54C4681AE9CF9200AF7477 /* Project object */ = { 441 | isa = PBXProject; 442 | attributes = { 443 | LastUpgradeCheck = 0630; 444 | ORGANIZATIONNAME = "Jean Lebrument"; 445 | TargetAttributes = { 446 | 4D54C46F1AE9CF9200AF7477 = { 447 | CreatedOnToolsVersion = 6.3; 448 | }; 449 | 4D54C4841AE9CF9200AF7477 = { 450 | CreatedOnToolsVersion = 6.3; 451 | TestTargetID = 4D54C46F1AE9CF9200AF7477; 452 | }; 453 | }; 454 | }; 455 | buildConfigurationList = 4D54C46B1AE9CF9200AF7477 /* Build configuration list for PBXProject "iOSModuleArchitecture" */; 456 | compatibilityVersion = "Xcode 3.2"; 457 | developmentRegion = English; 458 | hasScannedForEncodings = 0; 459 | knownRegions = ( 460 | en, 461 | Base, 462 | ); 463 | mainGroup = 4D54C4671AE9CF9200AF7477; 464 | productRefGroup = 4D54C4711AE9CF9200AF7477 /* Products */; 465 | projectDirPath = ""; 466 | projectRoot = ""; 467 | targets = ( 468 | 4D54C46F1AE9CF9200AF7477 /* iOSModuleArchitecture */, 469 | 4D54C4841AE9CF9200AF7477 /* iOSModuleArchitectureTests */, 470 | ); 471 | }; 472 | /* End PBXProject section */ 473 | 474 | /* Begin PBXResourcesBuildPhase section */ 475 | 4D54C46E1AE9CF9200AF7477 /* Resources */ = { 476 | isa = PBXResourcesBuildPhase; 477 | buildActionMask = 2147483647; 478 | files = ( 479 | 4D54C47B1AE9CF9200AF7477 /* Main.storyboard in Resources */, 480 | 4D54C4801AE9CF9200AF7477 /* LaunchScreen.xib in Resources */, 481 | 4D54C47D1AE9CF9200AF7477 /* Images.xcassets in Resources */, 482 | ); 483 | runOnlyForDeploymentPostprocessing = 0; 484 | }; 485 | 4D54C4831AE9CF9200AF7477 /* Resources */ = { 486 | isa = PBXResourcesBuildPhase; 487 | buildActionMask = 2147483647; 488 | files = ( 489 | ); 490 | runOnlyForDeploymentPostprocessing = 0; 491 | }; 492 | /* End PBXResourcesBuildPhase section */ 493 | 494 | /* Begin PBXShellScriptBuildPhase section */ 495 | 2E979EF55A9B38DCDD7AA24A /* Check Pods Manifest.lock */ = { 496 | isa = PBXShellScriptBuildPhase; 497 | buildActionMask = 2147483647; 498 | files = ( 499 | ); 500 | inputPaths = ( 501 | ); 502 | name = "Check Pods Manifest.lock"; 503 | outputPaths = ( 504 | ); 505 | runOnlyForDeploymentPostprocessing = 0; 506 | shellPath = /bin/sh; 507 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 508 | showEnvVarsInLog = 0; 509 | }; 510 | D7BE4C6E28EF0F1373CDF8D8 /* Copy Pods Resources */ = { 511 | isa = PBXShellScriptBuildPhase; 512 | buildActionMask = 2147483647; 513 | files = ( 514 | ); 515 | inputPaths = ( 516 | ); 517 | name = "Copy Pods Resources"; 518 | outputPaths = ( 519 | ); 520 | runOnlyForDeploymentPostprocessing = 0; 521 | shellPath = /bin/sh; 522 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 523 | showEnvVarsInLog = 0; 524 | }; 525 | /* End PBXShellScriptBuildPhase section */ 526 | 527 | /* Begin PBXSourcesBuildPhase section */ 528 | 4D54C46C1AE9CF9200AF7477 /* Sources */ = { 529 | isa = PBXSourcesBuildPhase; 530 | buildActionMask = 2147483647; 531 | files = ( 532 | 4DC58D541AE9FA4C00C6A015 /* SecondModuleViewController.swift in Sources */, 533 | 4D54C4C11AE9CFAA00AF7477 /* FirstModuleModel.swift in Sources */, 534 | 4DC58D521AE9FA4C00C6A015 /* SecondModulePresenter.swift in Sources */, 535 | 4D54C4B91AE9CFAA00AF7477 /* RootWireframe.swift in Sources */, 536 | 4DC58D511AE9FA4C00C6A015 /* SecondModuleIO.swift in Sources */, 537 | 4D54C4BD1AE9CFAA00AF7477 /* FirstModuleWebServiceDatastore.swift in Sources */, 538 | 4D54C4C41AE9CFAA00AF7477 /* FirstModuleIO.swift in Sources */, 539 | 4D54C4C21AE9CFAA00AF7477 /* FirstModuleBuilder.swift in Sources */, 540 | 4D54C4BE1AE9CFAA00AF7477 /* IFirstModuleRemoteDatastore.swift in Sources */, 541 | 4DC58D501AE9FA4C00C6A015 /* ISecondModuleIO.swift in Sources */, 542 | 4D54C4C01AE9CFAA00AF7477 /* FirstModuleInteractorIO.swift in Sources */, 543 | 4D54C4C71AE9CFAA00AF7477 /* FirstModuleViewController.swift in Sources */, 544 | 4D54C4B81AE9CFAA00AF7477 /* AppDelegate.swift in Sources */, 545 | 4DC58D4E1AE9FA4C00C6A015 /* ISecondModuleBuilder.swift in Sources */, 546 | 4D54C4BB1AE9CFAA00AF7477 /* FirstModuleLocalStorageDatastore.swift in Sources */, 547 | 4D54C4BA1AE9CFAA00AF7477 /* FirstModuleDatastore.swift in Sources */, 548 | 4D54C4C91AE9CFAA00AF7477 /* FirstModuleWireframe.swift in Sources */, 549 | 4D54C4C51AE9CFAA00AF7477 /* IFirstModuleIO.swift in Sources */, 550 | 4DC58D531AE9FA4C00C6A015 /* ISecondModuleView.swift in Sources */, 551 | 4D54C4BC1AE9CFAA00AF7477 /* IFirstModuleLocalDatastore.swift in Sources */, 552 | 4D54C4C81AE9CFAA00AF7477 /* IFirstModuleView.swift in Sources */, 553 | 4DC58D551AE9FA4C00C6A015 /* SecondModuleWireframe.swift in Sources */, 554 | 4D54C4C31AE9CFAA00AF7477 /* IFirstModuleBuilder.swift in Sources */, 555 | 4DC58D4F1AE9FA4C00C6A015 /* SecondModuleBuilder.swift in Sources */, 556 | 4D54C4C61AE9CFAA00AF7477 /* FirstModulePresenter.swift in Sources */, 557 | 4D54C4BF1AE9CFAA00AF7477 /* FirstModuleInteractor.swift in Sources */, 558 | ); 559 | runOnlyForDeploymentPostprocessing = 0; 560 | }; 561 | 4D54C4811AE9CF9200AF7477 /* Sources */ = { 562 | isa = PBXSourcesBuildPhase; 563 | buildActionMask = 2147483647; 564 | files = ( 565 | 4D54C48C1AE9CF9200AF7477 /* iOSModuleArchitectureTests.swift in Sources */, 566 | ); 567 | runOnlyForDeploymentPostprocessing = 0; 568 | }; 569 | /* End PBXSourcesBuildPhase section */ 570 | 571 | /* Begin PBXTargetDependency section */ 572 | 4D54C4871AE9CF9200AF7477 /* PBXTargetDependency */ = { 573 | isa = PBXTargetDependency; 574 | target = 4D54C46F1AE9CF9200AF7477 /* iOSModuleArchitecture */; 575 | targetProxy = 4D54C4861AE9CF9200AF7477 /* PBXContainerItemProxy */; 576 | }; 577 | /* End PBXTargetDependency section */ 578 | 579 | /* Begin PBXVariantGroup section */ 580 | 4D54C4791AE9CF9200AF7477 /* Main.storyboard */ = { 581 | isa = PBXVariantGroup; 582 | children = ( 583 | 4D54C47A1AE9CF9200AF7477 /* Base */, 584 | ); 585 | name = Main.storyboard; 586 | sourceTree = ""; 587 | }; 588 | 4D54C47E1AE9CF9200AF7477 /* LaunchScreen.xib */ = { 589 | isa = PBXVariantGroup; 590 | children = ( 591 | 4D54C47F1AE9CF9200AF7477 /* Base */, 592 | ); 593 | name = LaunchScreen.xib; 594 | sourceTree = ""; 595 | }; 596 | /* End PBXVariantGroup section */ 597 | 598 | /* Begin XCBuildConfiguration section */ 599 | 4D54C48D1AE9CF9200AF7477 /* Debug */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | ALWAYS_SEARCH_USER_PATHS = NO; 603 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 604 | CLANG_CXX_LIBRARY = "libc++"; 605 | CLANG_ENABLE_MODULES = YES; 606 | CLANG_ENABLE_OBJC_ARC = YES; 607 | CLANG_WARN_BOOL_CONVERSION = YES; 608 | CLANG_WARN_CONSTANT_CONVERSION = YES; 609 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 610 | CLANG_WARN_EMPTY_BODY = YES; 611 | CLANG_WARN_ENUM_CONVERSION = YES; 612 | CLANG_WARN_INT_CONVERSION = YES; 613 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 614 | CLANG_WARN_UNREACHABLE_CODE = YES; 615 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 616 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 617 | COPY_PHASE_STRIP = NO; 618 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 619 | ENABLE_STRICT_OBJC_MSGSEND = YES; 620 | GCC_C_LANGUAGE_STANDARD = gnu99; 621 | GCC_DYNAMIC_NO_PIC = NO; 622 | GCC_NO_COMMON_BLOCKS = YES; 623 | GCC_OPTIMIZATION_LEVEL = 0; 624 | GCC_PREPROCESSOR_DEFINITIONS = ( 625 | "DEBUG=1", 626 | "$(inherited)", 627 | ); 628 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 629 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 630 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 631 | GCC_WARN_UNDECLARED_SELECTOR = YES; 632 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 633 | GCC_WARN_UNUSED_FUNCTION = YES; 634 | GCC_WARN_UNUSED_VARIABLE = YES; 635 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 636 | MTL_ENABLE_DEBUG_INFO = YES; 637 | ONLY_ACTIVE_ARCH = YES; 638 | SDKROOT = iphoneos; 639 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 640 | }; 641 | name = Debug; 642 | }; 643 | 4D54C48E1AE9CF9200AF7477 /* Release */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | ALWAYS_SEARCH_USER_PATHS = NO; 647 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 648 | CLANG_CXX_LIBRARY = "libc++"; 649 | CLANG_ENABLE_MODULES = YES; 650 | CLANG_ENABLE_OBJC_ARC = YES; 651 | CLANG_WARN_BOOL_CONVERSION = YES; 652 | CLANG_WARN_CONSTANT_CONVERSION = YES; 653 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 654 | CLANG_WARN_EMPTY_BODY = YES; 655 | CLANG_WARN_ENUM_CONVERSION = YES; 656 | CLANG_WARN_INT_CONVERSION = YES; 657 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 658 | CLANG_WARN_UNREACHABLE_CODE = YES; 659 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 660 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 661 | COPY_PHASE_STRIP = NO; 662 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 663 | ENABLE_NS_ASSERTIONS = NO; 664 | ENABLE_STRICT_OBJC_MSGSEND = YES; 665 | GCC_C_LANGUAGE_STANDARD = gnu99; 666 | GCC_NO_COMMON_BLOCKS = YES; 667 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 668 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 669 | GCC_WARN_UNDECLARED_SELECTOR = YES; 670 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 671 | GCC_WARN_UNUSED_FUNCTION = YES; 672 | GCC_WARN_UNUSED_VARIABLE = YES; 673 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 674 | MTL_ENABLE_DEBUG_INFO = NO; 675 | SDKROOT = iphoneos; 676 | VALIDATE_PRODUCT = YES; 677 | }; 678 | name = Release; 679 | }; 680 | 4D54C4901AE9CF9200AF7477 /* Debug */ = { 681 | isa = XCBuildConfiguration; 682 | baseConfigurationReference = 042C63B78896715096D47E28 /* Pods.debug.xcconfig */; 683 | buildSettings = { 684 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 685 | INFOPLIST_FILE = iOSModuleArchitecture/Info.plist; 686 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 687 | PRODUCT_NAME = "$(TARGET_NAME)"; 688 | SWIFT_OBJC_BRIDGING_HEADER = "iOSModuleArchitecture/Code/iOSModuleArchitecture-Bridging-Header"; 689 | "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = "iOSModuleArchitecture/Code/iOSModuleArchitecture-Bridging-Header.h"; 690 | }; 691 | name = Debug; 692 | }; 693 | 4D54C4911AE9CF9200AF7477 /* Release */ = { 694 | isa = XCBuildConfiguration; 695 | baseConfigurationReference = DBF2111F7C7CD118CA868498 /* Pods.release.xcconfig */; 696 | buildSettings = { 697 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 698 | INFOPLIST_FILE = iOSModuleArchitecture/Info.plist; 699 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 700 | PRODUCT_NAME = "$(TARGET_NAME)"; 701 | "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = "iOSModuleArchitecture/Code/iOSModuleArchitecture-Bridging-Header.h"; 702 | }; 703 | name = Release; 704 | }; 705 | 4D54C4931AE9CF9200AF7477 /* Debug */ = { 706 | isa = XCBuildConfiguration; 707 | buildSettings = { 708 | BUNDLE_LOADER = "$(TEST_HOST)"; 709 | FRAMEWORK_SEARCH_PATHS = ( 710 | "$(SDKROOT)/Developer/Library/Frameworks", 711 | "$(inherited)", 712 | ); 713 | GCC_PREPROCESSOR_DEFINITIONS = ( 714 | "DEBUG=1", 715 | "$(inherited)", 716 | ); 717 | INFOPLIST_FILE = iOSModuleArchitectureTests/Info.plist; 718 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 719 | PRODUCT_NAME = "$(TARGET_NAME)"; 720 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSModuleArchitecture.app/iOSModuleArchitecture"; 721 | }; 722 | name = Debug; 723 | }; 724 | 4D54C4941AE9CF9200AF7477 /* Release */ = { 725 | isa = XCBuildConfiguration; 726 | buildSettings = { 727 | BUNDLE_LOADER = "$(TEST_HOST)"; 728 | FRAMEWORK_SEARCH_PATHS = ( 729 | "$(SDKROOT)/Developer/Library/Frameworks", 730 | "$(inherited)", 731 | ); 732 | INFOPLIST_FILE = iOSModuleArchitectureTests/Info.plist; 733 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 734 | PRODUCT_NAME = "$(TARGET_NAME)"; 735 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSModuleArchitecture.app/iOSModuleArchitecture"; 736 | }; 737 | name = Release; 738 | }; 739 | /* End XCBuildConfiguration section */ 740 | 741 | /* Begin XCConfigurationList section */ 742 | 4D54C46B1AE9CF9200AF7477 /* Build configuration list for PBXProject "iOSModuleArchitecture" */ = { 743 | isa = XCConfigurationList; 744 | buildConfigurations = ( 745 | 4D54C48D1AE9CF9200AF7477 /* Debug */, 746 | 4D54C48E1AE9CF9200AF7477 /* Release */, 747 | ); 748 | defaultConfigurationIsVisible = 0; 749 | defaultConfigurationName = Release; 750 | }; 751 | 4D54C48F1AE9CF9200AF7477 /* Build configuration list for PBXNativeTarget "iOSModuleArchitecture" */ = { 752 | isa = XCConfigurationList; 753 | buildConfigurations = ( 754 | 4D54C4901AE9CF9200AF7477 /* Debug */, 755 | 4D54C4911AE9CF9200AF7477 /* Release */, 756 | ); 757 | defaultConfigurationIsVisible = 0; 758 | defaultConfigurationName = Release; 759 | }; 760 | 4D54C4921AE9CF9200AF7477 /* Build configuration list for PBXNativeTarget "iOSModuleArchitectureTests" */ = { 761 | isa = XCConfigurationList; 762 | buildConfigurations = ( 763 | 4D54C4931AE9CF9200AF7477 /* Debug */, 764 | 4D54C4941AE9CF9200AF7477 /* Release */, 765 | ); 766 | defaultConfigurationIsVisible = 0; 767 | defaultConfigurationName = Release; 768 | }; 769 | /* End XCConfigurationList section */ 770 | }; 771 | rootObject = 4D54C4681AE9CF9200AF7477 /* Project object */; 772 | } 773 | -------------------------------------------------------------------------------- /iOSModuleArchitecture.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOSModuleArchitecture.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // iOSModuleArchitecture 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Common/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PassingData 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | 19 | JLRoutes.addRoute("/firstModule", handler:{param -> Bool in 20 | 21 | let firstModule = FirstModuleBuilder().createFirstModule() 22 | 23 | firstModule?.launchModule(self.window!) 24 | 25 | return true 26 | }) 27 | 28 | JLRoutes.addRoute("/secondModule", handler:{param -> Bool in 29 | 30 | if let value = param["value"] as? String 31 | { 32 | if let secondModule = SecondModuleBuilder().createSecondModule(value) 33 | { 34 | secondModule.launchModule(self.window!) 35 | } 36 | } 37 | 38 | return true 39 | }) 40 | 41 | println("Launching the route") 42 | 43 | UIApplication.sharedApplication().openURL(NSURL(string: "myself://firstModule")!) 44 | 45 | return true 46 | } 47 | 48 | func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool 49 | { 50 | return JLRoutes.routeURL(url) 51 | } 52 | 53 | func applicationWillResignActive(application: UIApplication) { 54 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 55 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 56 | } 57 | 58 | func applicationDidEnterBackground(application: UIApplication) { 59 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 60 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 61 | } 62 | 63 | func applicationWillEnterForeground(application: UIApplication) { 64 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 65 | } 66 | 67 | func applicationDidBecomeActive(application: UIApplication) { 68 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 69 | } 70 | 71 | func applicationWillTerminate(application: UIApplication) { 72 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 73 | } 74 | 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Common/RootWireframe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RootWireframe.m 3 | // 4 | // Created by Jean Lebrument on 04/23/2015. 5 | // 6 | 7 | import UIKit 8 | 9 | class RootWireframe 10 | { 11 | class func showViewController(viewController: UIViewController, inWindow window: UIWindow) 12 | { 13 | navigationControllerFromWindow(window)?.pushViewController(viewController, animated: true) 14 | } 15 | 16 | class func navigationControllerFromWindow(window: UIWindow) -> UINavigationController? 17 | { 18 | return window.rootViewController as? UINavigationController 19 | } 20 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Datastore/FirstModuleDatastore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleDatastore.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModuleDatastore 10 | { 11 | var localDatastore: IFirstModuleLocalDatastore? 12 | var remoteDatastore: IFirstModuleRemoteDatastore? 13 | 14 | init(){} 15 | 16 | func retrieveData(completion: FirstModuleModel? -> Void) 17 | { 18 | remoteDatastore?.retrieveData({ data in _ = () 19 | (data != nil) ? completion(data) : self.localDatastore?.retrieveData(completion) 20 | }) 21 | } 22 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Datastore/LocalDatastore/FirstModuleLocalStorageDatastore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleLocalStorageDatastore.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModuleLocalStorageDatastore: IFirstModuleLocalDatastore 10 | { 11 | init(){} 12 | 13 | func retrieveData(completion: FirstModuleModel? -> Void) 14 | { 15 | let data = FirstModuleModel() 16 | 17 | data.str = "A" 18 | 19 | completion(data) 20 | } 21 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Datastore/LocalDatastore/IFirstModuleLocalDatastore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IFirstModuleLocalDataStore.swift 3 | // ModuleArchitecture 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol IFirstModuleLocalDatastore 12 | { 13 | func retrieveData(completion: FirstModuleModel? -> Void) 14 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Datastore/RemoteDatastore/FirstModuleWebServiceDatastore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleWebServiceDatastore.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModuleWebServiceDatastore: IFirstModuleRemoteDatastore 10 | { 11 | init(){} 12 | 13 | func retrieveData(completion: FirstModuleModel? -> Void) 14 | { 15 | completion(nil) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Datastore/RemoteDatastore/IFirstModuleRemoteDatastore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IFirstModuleRemoteDataStore.swift 3 | // ModuleArchitecture 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol IFirstModuleRemoteDatastore 12 | { 13 | func retrieveData(completion: FirstModuleModel? -> Void) 14 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Interactor/FirstModuleInteractor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleInteractor.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModuleInteractor : IFirstModuleInteractorInput 10 | { 11 | weak var output : IFirstModuleInteractorOutput? 12 | var datastore : FirstModuleDatastore? 13 | 14 | func findData() 15 | { 16 | datastore?.retrieveData({ [unowned self] data in 17 | self.output?.foundData(data) 18 | }) 19 | } 20 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Interactor/FirstModuleInteractorIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleInteractorIO.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | protocol IFirstModuleInteractorInput : class 8 | { 9 | func findData() 10 | } 11 | 12 | protocol IFirstModuleInteractorOutput: class 13 | { 14 | func foundData(data : FirstModuleModel?) 15 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Application Logic/Model/FirstModuleModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleModel 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModuleModel 10 | { 11 | var str: String? 12 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Factory/FirstModuleBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleBuilder.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15 5 | // 6 | 7 | class FirstModuleBuilder: IFirstModuleBuilder 8 | { 9 | func createFirstModule() -> FirstModuleIO? 10 | { 11 | let wireframe = FirstModuleWireframe() 12 | let presenter = FirstModulePresenter() 13 | let interactor = FirstModuleInteractor() 14 | let datastore = FirstModuleDatastore() 15 | let io = FirstModuleIO() 16 | 17 | presenter.output = io 18 | presenter.interactor = interactor 19 | interactor.datastore = datastore 20 | interactor.output = presenter 21 | datastore.localDatastore = FirstModuleLocalStorageDatastore() 22 | datastore.remoteDatastore = FirstModuleWebServiceDatastore() 23 | 24 | io.presenter = presenter 25 | io.wireframe = wireframe 26 | 27 | return io 28 | } 29 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/Factory/IFirstModuleBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IFirstModuleBuilder.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15 5 | // 6 | 7 | protocol IFirstModuleBuilder 8 | { 9 | func createFirstModule() -> FirstModuleIO? 10 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/IO/FirstModuleIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleIO.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class FirstModuleIO 11 | { 12 | var wireframe: FirstModuleWireframe? 13 | var presenter: FirstModulePresenter? 14 | 15 | init(){} 16 | } 17 | 18 | extension FirstModuleIO: IFirstModuleInput 19 | { 20 | func launchModule(window: UIWindow) 21 | { 22 | wireframe?.presentInterfaceFromWindow(UIApplication.sharedApplication().windows[0] as! UIWindow) 23 | 24 | wireframe?.viewController?.eventHandler = presenter 25 | presenter?.userInterface = wireframe?.viewController 26 | } 27 | } 28 | 29 | extension FirstModuleIO: IFirstModuleOutput 30 | { 31 | func goToOutputModule(data: FirstModuleModel) 32 | { 33 | if let str = data.str 34 | { 35 | UIApplication.sharedApplication().openURL(NSURL(string: "myself://secondModule?value=\(str)")!) 36 | } 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/IO/IFirstModuleIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IFirstModuleIO.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | protocol IFirstModuleInput: class 11 | { 12 | func launchModule(window: UIWindow) 13 | } 14 | 15 | protocol IFirstModuleOutput: class 16 | { 17 | func goToOutputModule(data: FirstModuleModel) 18 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/User Interface/Presenter/FirstModulePresenter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModulePresenter.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class FirstModulePresenter 10 | { 11 | var interactor : IFirstModuleInteractorInput? 12 | weak var userInterface : IFirstModuleView? 13 | var output : IFirstModuleOutput? 14 | 15 | init(){} 16 | } 17 | 18 | extension FirstModulePresenter 19 | { 20 | func updateView() 21 | { 22 | interactor?.findData() 23 | } 24 | 25 | func goToSecondModule(data: FirstModuleModel?) 26 | { 27 | if let sData = data 28 | { 29 | output?.goToOutputModule(sData) 30 | } 31 | } 32 | } 33 | 34 | extension FirstModulePresenter : IFirstModuleInteractorOutput 35 | { 36 | func foundData(data : FirstModuleModel?) 37 | { 38 | userInterface?.showData(data) 39 | } 40 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/User Interface/View/FirstModuleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleViewController.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class FirstModuleViewController: UIViewController 11 | { 12 | var eventHandler: FirstModulePresenter? 13 | var data: FirstModuleModel? 14 | 15 | @IBOutlet weak var dataValueField: UITextField! 16 | 17 | override func viewDidLoad() 18 | { 19 | super.viewDidLoad() 20 | 21 | eventHandler?.updateView() 22 | } 23 | 24 | @IBAction func clickButton(sender: AnyObject) 25 | { 26 | eventHandler?.goToSecondModule(data) 27 | } 28 | } 29 | 30 | extension FirstModuleViewController : IFirstModuleView 31 | { 32 | func showData(tmpData: FirstModuleModel?) 33 | { 34 | data = tmpData 35 | dataValueField.text = data?.str 36 | } 37 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/User Interface/View/IFirstModuleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IFirstModuleView.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | protocol IFirstModuleView: class 10 | { 11 | func showData(data: FirstModuleModel?) 12 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/FirstModule/User Interface/Wireframe/FirstModuleWireframe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FirstModuleWireframe.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class FirstModuleWireframe 11 | { 12 | weak var viewController: FirstModuleViewController! 13 | let FirstModuleViewControllerIdentifier = "FirstModuleViewController" 14 | 15 | init(){} 16 | 17 | func presentInterfaceFromWindow(window: UIWindow) 18 | { 19 | let tmpViewController = FirstModuleViewControllerromStoryboard() 20 | 21 | RootWireframe.showViewController(tmpViewController, inWindow: window) 22 | 23 | viewController = tmpViewController 24 | } 25 | 26 | func FirstModuleViewControllerromStoryboard() -> FirstModuleViewController 27 | { 28 | let storyboard = mainStoryboard() 29 | let tmpViewController = storyboard.instantiateViewControllerWithIdentifier(FirstModuleViewControllerIdentifier) as! FirstModuleViewController 30 | 31 | return tmpViewController 32 | } 33 | 34 | func mainStoryboard() -> UIStoryboard 35 | { 36 | let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) 37 | 38 | return storyboard 39 | } 40 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/Factory/ISecondModuleBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ISecondModuleBuilder.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15 5 | // 6 | 7 | protocol ISecondModuleBuilder 8 | { 9 | func createSecondModule(value: String) -> SecondModuleIO? 10 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/Factory/SecondModuleBuilder.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondModuleBuilder.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15 5 | // 6 | 7 | class SecondModuleBuilder: ISecondModuleBuilder 8 | { 9 | func createSecondModule(value: String) -> SecondModuleIO? 10 | { 11 | let wireframe = SecondModuleWireframe() 12 | let presenter = SecondModulePresenter() 13 | let io = SecondModuleIO() 14 | 15 | presenter.output = io 16 | presenter.value = value 17 | 18 | io.presenter = presenter 19 | io.wireframe = wireframe 20 | 21 | return io 22 | } 23 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/IO/ISecondModuleIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ISecondModuleIO.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | protocol ISecondModuleInput: class 11 | { 12 | func launchModule(window: UIWindow) 13 | } 14 | 15 | protocol ISecondModuleOutput: class 16 | { 17 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/IO/SecondModuleIO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondModuleIO.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class SecondModuleIO 11 | { 12 | var wireframe: SecondModuleWireframe? 13 | var presenter: SecondModulePresenter? 14 | 15 | init(){} 16 | } 17 | 18 | extension SecondModuleIO: ISecondModuleInput 19 | { 20 | func launchModule(window: UIWindow) 21 | { 22 | wireframe?.presentInterfaceFromWindow(UIApplication.sharedApplication().windows[0] as! UIWindow) 23 | 24 | wireframe?.viewController?.eventHandler = presenter 25 | presenter?.userInterface = wireframe?.viewController 26 | } 27 | } 28 | 29 | extension SecondModuleIO: ISecondModuleOutput 30 | { 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/User Interface/Presenter/SecondModulePresenter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondModulePresenter.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | class SecondModulePresenter 10 | { 11 | var value: String? 12 | 13 | weak var userInterface : ISecondModuleView? 14 | var output : ISecondModuleOutput? 15 | 16 | init(){} 17 | 18 | func updateView() 19 | { 20 | userInterface?.showValue(value) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/User Interface/View/ISecondModuleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ISecondModuleView.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import Foundation 8 | 9 | protocol ISecondModuleView: class 10 | { 11 | func showValue(value: String?) 12 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/User Interface/View/SecondModuleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondModuleViewController.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/14. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class SecondModuleViewController: UIViewController 11 | { 12 | var eventHandler: SecondModulePresenter? 13 | 14 | @IBOutlet weak var valueTextField: UITextField! 15 | 16 | override func viewDidLoad() 17 | { 18 | super.viewDidLoad() 19 | 20 | eventHandler?.updateView() 21 | } 22 | } 23 | 24 | extension SecondModuleViewController : ISecondModuleView 25 | { 26 | func showValue(value: String?) 27 | { 28 | if let sValue = value 29 | { 30 | valueTextField.text = valueTextField.text + sValue 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/Modules/SecondModule/User Interface/Wireframe/SecondModuleWireframe.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SecondModuleWireframe.swift 3 | // 4 | // Created by Jean Lebrument on 04/23/15. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | class SecondModuleWireframe 11 | { 12 | weak var viewController : SecondModuleViewController? 13 | 14 | let SecondModuleViewControllerIdentifier = "SecondModuleViewController" 15 | 16 | init(){} 17 | 18 | func presentInterfaceFromWindow(window: UIWindow) 19 | { 20 | let tmpViewController = SecondModuleViewControllerFromStoryboard() 21 | 22 | RootWireframe.showViewController(tmpViewController, inWindow: window) 23 | 24 | viewController = tmpViewController 25 | } 26 | 27 | func SecondModuleViewControllerFromStoryboard() -> SecondModuleViewController 28 | { 29 | let storyboard = mainStoryboard() 30 | let tmpViewController = storyboard.instantiateViewControllerWithIdentifier(SecondModuleViewControllerIdentifier) as! SecondModuleViewController 31 | 32 | return tmpViewController 33 | } 34 | 35 | func mainStoryboard() -> UIStoryboard 36 | { 37 | let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) 38 | 39 | return storyboard 40 | } 41 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Code/iOSModuleArchitecture-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // iOSModuleArchitecture-Bridging-Header.h 3 | // ModuleArchitecture 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | #ifndef ModuleArchitecture_iOSModuleArchitecture_Bridging_Header_h 10 | #define ModuleArchitecture_iOSModuleArchitecture_Bridging_Header_h 11 | 12 | #import "JLRoutes.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /iOSModuleArchitecture/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | JeanLebrument.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | LSApplicationCategoryType 34 | 35 | 36 | CFBundleURLName 37 | 38 | 39 | 40 | CFBundleURLTypes 41 | 42 | 43 | CFBundleURLName 44 | com.iOSModuleArchitecture 45 | CFBundleURLSchemes 46 | 47 | myself 48 | 49 | 50 | 51 | UISupportedInterfaceOrientations 52 | 53 | UIInterfaceOrientationPortrait 54 | UIInterfaceOrientationLandscapeLeft 55 | UIInterfaceOrientationLandscapeRight 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /iOSModuleArchitecture/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // iOSModuleArchitecture 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /iOSModuleArchitectureTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | JeanLebrument.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOSModuleArchitectureTests/iOSModuleArchitectureTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // iOSModuleArchitectureTests.swift 3 | // iOSModuleArchitectureTests 4 | // 5 | // Created by Jean Lebrument on 4/23/15. 6 | // Copyright (c) 2015 Jean Lebrument. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class iOSModuleArchitectureTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------