All Projects → kudoleh → Ios Modular Architecture

kudoleh / Ios Modular Architecture

Template iOS application using Modular Architecture

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Ios Modular Architecture

Android Kotlin Mvi Cleanarchitecture
Android + Kotlin + Modularization + Gradle Depedency managment + Gradle written in Kotlin DSL + Custom Gradle Plugin + MVVM + MVI + Clean Architecture + Repository Pattern + Coroutines + Flows + Koin + Retrofit2 + ROOM + Kotlin-Android-Extension + KtLints
Stars: ✭ 187 (-1.58%)
Mutual labels:  clean-architecture, modularization
Stocker
Stocker is a currency monitoring app. It offers instant currency rates of banks.
Stars: ✭ 38 (-80%)
Mutual labels:  clean-architecture, modularization
Kotlin Modular Tdd Coroutines Mvvm
A sample Kotlin app which was built with modular structure, Kotlin DSL, Kotlin Coroutines, TDD and MVVM patterns.
Stars: ✭ 256 (+34.74%)
Mutual labels:  clean-architecture, modularization
TVToday
iOS TV Shows app with TMDb Api. RxSwift, MVVM, Clean Architecture. Tuist + Swift Package Manager
Stars: ✭ 27 (-85.79%)
Mutual labels:  clean-architecture, ios-app
Modular App Core
Core implementations for a modular Android App
Stars: ✭ 127 (-33.16%)
Mutual labels:  clean-architecture, modularization
FootballNews2
Personal Android project for Football daily updates
Stars: ✭ 16 (-91.58%)
Mutual labels:  clean-architecture, modularization
Avsqldebugger
A Simple Core Data Debugger that will look inside your apps DB
Stars: ✭ 30 (-84.21%)
Mutual labels:  ios-app, cocoapods
Games
The Games app has two features which are listing and showing detail of games.
Stars: ✭ 15 (-92.11%)
Mutual labels:  clean-architecture, modularization
Kotlin Mpp Standard
A standard setup for Kotlin multiplatform projects.
Stars: ✭ 92 (-51.58%)
Mutual labels:  ios-app, cocoapods
Slidingtabbar
A custom TabBar view with sliding animation written in Swift.
Stars: ✭ 84 (-55.79%)
Mutual labels:  ios-app, cocoapods
BESTV
Android TV App powered by TMDb. It is a easy way to find the best TV content, the top movies, series... all of that in your TV.
Stars: ✭ 49 (-74.21%)
Mutual labels:  clean-architecture, modularization
Decouplingkit
decoupling between modules in your iOS Project. iOS模块化过程中模块间解耦方案
Stars: ✭ 136 (-28.42%)
Mutual labels:  cocoapods, modularization
movies
An example approach for modularization, reactive clean architecture and persistancy.
Stars: ✭ 110 (-42.11%)
Mutual labels:  clean-architecture, modularization
Android Kotlin Modulerized Cleanarchitecture
🚀 Example modularized android application with single activity written in Kotlin
Stars: ✭ 180 (-5.26%)
Mutual labels:  clean-architecture, modularization
MVI-Clean-Architecture
MVI + Clean Architecture + Best Practices | Example of Clean Architecture of Android app using MVI design pattern with Jetpack and popular libraries
Stars: ✭ 50 (-73.68%)
Mutual labels:  clean-architecture, modularization
Kotlin Native Superhero App
Android and iOS master detail application for list Marvel Super Heroes
Stars: ✭ 15 (-92.11%)
Mutual labels:  ios-app, clean-architecture
Insights For Instagram
A simple iOS Instagram's media insights App written in Swift
Stars: ✭ 193 (+1.58%)
Mutual labels:  ios-app, clean-architecture
Gitiny
An iOS app for GitHub with exploring trending
Stars: ✭ 247 (+30%)
Mutual labels:  ios-app, clean-architecture
Mojilist
🛍 Create shopping lists with emojis!
Stars: ✭ 60 (-68.42%)
Mutual labels:  ios-app, cocoapods
Propertyfindar
🏘 🎃 Real Estate Sample App with RxJava3+Coroutines Flow, Dynamic Feature Modules, Dagger Hilt, Offline First, ConcatAdapter, Animations and tests for Room, Retrofit, useCase and ViewModels with TDD.
Stars: ✭ 133 (-30%)
Mutual labels:  clean-architecture, modularization

Modular Architecture on iOS   CI

iOS Project implemented with Modular Architecture. (Can be used as Template project by replacing item name “Movie”). More information in medium post: Medium Post about Modular Architecture

Alt text More information in medium post: Medium Post

Including Authentication module (initial scaling)

Modules Dependencies with Authentication

More information in medium post: Medium Post

How it can scale:

Open medium to read about

Check medium post for more information: Medium Post

Video 1: Extracting Networking Service Module. see steps

Play video

Video 2: Extracting Movies Search Feature Module. see steps

Play video

Requirements:

  • Xcode Version 11.2.1+ Swift 5.0+ CocoaPods 1.8.4+

Steps to create module

  • Step 1. Setup App project with CocoaPods: (Video 1 00:06)

    • Open Terminal and change directory cd to folder with your project App.xcodeproj file, and execute following commands:
      • pod init
      • inside Podfile
        • uncomment platform :ios, '9.0', and change '9.0' to 10.0 or 11.0
        • add line: workspace 'AppName.xcworkspace'
        • add line: project 'AppName.xcodeproj'
      • pod install
  • Step 2. Create new Module with CocoaPods: (Video 1 00:48)

    • In the same folder from previous step create a new folder with name DevPods:

      • mkdir DevPods
    • Create New Module inside DevPods folder:

      • cd DevPods
      • pod lib create ModuleName
      • with Platform: iOS; Language: Swift; Include a Demo App: Yes; Test framework and view based testing we can skip

      Note: To use your own pod-template you can add the parameter --template-url=URL where URL is the git repo containing a compatible template.

  • Step 3. The Module's Example Demo project will be opened automatically, we need to update iOS and Swift versions: (Video 1 01:27)

    • Select example project and set In Deployment Info to iOS 10.0 or iOS 11.0
    • In Build Settings search for Swift and set Swift Language Version to Swift 5.
    • Remove Test Target and Test folder inside the project
    • Close this demo example project (otherwise you will not be able to open it from App.xcworkspace)
  • Step 4. Cleaning up DevPods/ModuleName folder: (Video 1 01:48)

    • Show hidden files with Cmd + Shift + . and delete files: .git, .gitignore and .travis.yamls
    • Delete files: _Pod.xcodeproj, Example/Podfile, Example/Podfile.lock, Example/Pods, Example/ModuleName.xcworkspace
  • Step 5. Edit Podfile of project located in same folder as app's project App.xcworkspace file: (Video 1 02:10)

    • Add module_name_pod inside Podfile:

       def module_name_pod
           pod 'ModuleName', :path => 'DevPods/ModuleName'
       end
      
    • Move nested test targets outside target 'App':

       target 'App' do
       ...
       end
      
       target 'AppTests' do
       	inherit! :search_paths
       end
       
       target 'AppUITests' do
       end
      
    • Add module's example target so we can develop this module from same main App's workspace:

       target 'ModuleName_Example' do
       	use_frameworks!
       	project 'DevPods/ModuleName/Example/ModuleName.xcodeproj'
       	
       	module_name_pod
       end
      
  • Step 6. Move files from main App into Module's Pod: (Video 1 03:14)

    • Inside DevPods/ModuleName/ModuleName folder remove Assets and Classes folders and create folder with name Module.
    • Move from main App to the Module folder all module's files (e.g. .swift, .xcassets, .storyboard, .xcdatamodeld...). After moving them from main App do not forget to delete them also from main App's target. For moving files is better to not use Xcode, and do it manually or with terminal.
      • Edit ModuleName.podspec:
        • Set ios deployment target: s.ios.deployment_target = '10.0' or 11.0

        • Replace s.source_files = ... to: (Video 1 03:53)

          s.source_files = 'MoviesSearch/Module/**/*.{swift}'
          s.resources = "MoviesSearch/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}"
          

          Note: if you have Core Data model with xcdatamodel extension you will need to convert it into xcdatamodeld by selecting this file and Editor or Help -> Add Model Version..

          Note: when you create new Group inside Development Pods/ModuleName with Xcode, it places its folder in wrong place outside of Module (pod folder). And it needs to be moved manually into Module folder using Finder, and then pod install

  • Step 7. Add all internal or external dependencies for this module. Add them inside ModuleName.podspec file located inside DevPods/ModuleName folder: (Video 2 03:33)

      # internal dependency (module you have created before)
      s.dependency 'ModuleName2' 
    
      # external dependency 3rd party framework 
      s.dependency 'PromiseKit'
    

Note: If you have not yet extracted your dependency and you need it here you can delegate this functionality to main App. Just create interface using protocol and implement it inside your main App. For example if you need to open chat from your module, then create protocol interface inside your module with function openChat(forUserId:inView:) and then implement it inside main App, and it will be injected from main App into DIContainer of the module. Also closures or delegation can be used.

  • Step 8. After pod install and compiling main App we will see some errors that we have to fix: (Video 2 03:45)
    • Inside main app, add import ModuleName in all files where it is needed

    • Change to public all types or functions that needs to be accessed from outside of the module, from main app or other module

    • Change all resources initialisers to initialise them with module's bundle (e.g. images, storyboards, nibs or CoreData models xcdatamodeld): (Video 2 05:15)

      // Image load from bundle
      UIImage(named: "image_name", in: Bundle(for: Self.self), compatibleWith: nil)
      // Image Literal
      final class LiteralBundleImage: _ExpressibleByImageLiteral {
      	let image: UIImage?
      	required init(imageLiteralResourceName name: String) {
      		image = UIImage(named: name, in: Bundle(for: Self.self), compatibleWith: nil)
      	}
      }
      let image = (#imageLiteral(resourceName: "image_name") as LiteralBundleImage)
      
      // Storyboards and Nibs load from bundle
      UIStoryboard(name: "name", bundle: Bundle(for: Self.self))
      UINib(nibName: "name", bundle: Bundle(for: Self.self))
      
      // Core Data model load from bundle
      guard let modelURL = Bundle(for: Self.self).url(forResource: "ModelFileName", withExtension: "momd"),
            let mom = NSManagedObjectModel(contentsOf: modelURL)
            else {
                  fatalError("Unable to located Core Data model")
      }
      let container = NSPersistentContainer(name: "Name", managedObjectModel: mom)
      
        Note: the file must have .xcdatamodeld extension, to convert it from xcdatamodel extension just Add Model Version..
        
    
  • Step 9. Move Module's tests from main App into module's Pod: (Video 2 07:20)
    • Crete folder with name Tests inside DevPods/ModuleName/ModuleName/

    • Move all files with tests from main App folder to DevPods/ModuleName/ModuleName/Tests. Note: Move them manually or using terminal, avoid doing it directly with Xcode groups.

    • Add to ModuleName.podspec:

      s.test_spec 'Tests' do |test_spec|
          test_spec.source_files = 'ModuleName/Tests/**/*.{swift}'
      end
      
    • Add to main App's Podfile module's pod , :testspecs => ['Tests']

      def module_name_pod
      	pod 'ModuleName', :path => 'DevPods/ModuleName', :testspecs => ['Tests']
      end
      
      • Add to all unit tests files imports: @testable import ModuleName
      • Run in terminal pod install for main App Podfile
      • To make our Module's unit test app to run unit test with Cmd + U from main App schema:
      • Edit schema ModuleName-Example, inside Test section, add unit tests from Pod: under Pod -> ModuleName-Unit-Tests
  • Step 10. Fix ModuleName-Example schema used for developing module in isolation: (Video 2 09:45)
    • Switch from main App schema to ModuleName-Example schema and try to build
    • Note: AppDelegate method will have some warning and error that we have to fix, you can just copy paste it form main App
  • Step 11. To make our Module's Example app to run unit test with Cmd + U, we follow the same step as we did for main App: (Video 2 10:10)
    • Edit schema ModuleName-Example, inside Test section, add unit tests from Pod: under Pod -> ModuleName-Unit-Tests

Module as Static Library [Optional]:

  • Change your modules to be as Static Libraries (We made it as Dynamic Library in previous steps):
    • Remove from main App's Podfile: use_frameworks!

    • Replace s.resources with s.resource_bundles in all modules' .podspec files (ModuleName.podspec):
      Note: resource_bundles has different structure: 'ModuleName' => [ ... ], where 'ModuleName' is bundle name:

      s.resources = 'ModuleName/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}'
      

      Replace s.resources with:

      s.resource_bundles = {
      	'ModuleName' => ['ModuleName/Module/**/*.{xcassets,json,storyboard,xib,xcdatamodeld}']
      }
      
    • Replace all Bundle(for: Self.self) appearances with call to extension: Bundle(for: Self.self).resource

       extension Bundle {
           var resource: Bundle {
              return Bundle(url: resourceURL!.appendingPathComponent("ModuleName.bundle"))!
           }
       }
      
    • If you have CoreData inside a module then open .xcdatamodeld file and change Codegen to Manual/None and Create NSManagedObject Subclass.. for all entities

Module's Testing in CI/CD [Optional]:

  • To keep always our modules buildable we need to build and run tests for each module on our Pipeline in CI. As example we can use Fastlane and Travis CI:

    • Fastlane script

       lane :test do |options|
       
         # Check if all modules are buildable
         all_modules_schemes.each do |s|
           UI.message "Testing if module #{s} is buildable"
           scan(
             scheme: s,
             device: simulator,
             build_for_testing: true,
           )
         end
       	
         # Run all unit and UI tests, and test if App is buildable
         scan(
           scheme: "App",
           device: simulator,
         )
       	
       end
      
    • Travis CI script

       os: osx
       osx_image: xcode11.2
       language: swift
       script:
       - fastlane test
      

Check medium post for more information: Medium Post

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].