GithubHelp home page GithubHelp logo

heliomesquita / marcopolo Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 214 KB

MarcoPolo is a library that combines coordinator and internal deep linking in a unique and simple solution.

License: MIT License

Swift 94.94% Ruby 5.06%
cocoapods coordinator coordinator-pattern deeplink deeplinking swift-package-manager ios swift xcodegen

marcopolo's Introduction

Swift Version License Swift Package Manager CocoaPods Compatible

MarcoPolo


Swiftmazing Logo

MarcoPolo is a library that combines coordinator and internal deep linking in a unique and simple solution.

Propose to solve

Developing a scalable solution is a problem, especially when it becomes modular. One reason is that the way the iOS system manages navigation is very limited.

To workaround this limitation, We can use the coordinator pattern. This pattern handles all screen navigation and is typically used with MVVM, creating the famous MVVM-C.

The coordinator pattern solves the problem for middle and small applications, but it gets messy when the app gets too big. The standard solution to this problem is creating a coordinator for each feature and having a primary coordinator take all of them. But when We decide to use multiple coordinators is the step to start a modular application.

The modular solution works well until we get some needs like feature A open feature B and feature B open feature A. Then, we could import feature B into feature A and solve this problem, but this is not true because we can not have cyclic dependence. To fix this problem, We can use internal deep-link to handle the next screen without creating dependencies between modules, avoiding dependency hell and cycle dependency.

This library implements both patterns in a straightforward way

Features

  • Coordinator
  • Deep-linking using url scheme

Requirements

  • iOS 10.0+
  • Xcode 14.2+

Installation

CocoaPods

You can use CocoaPods to install MarcoPolo by adding it to your Podfile:

platform :ios, '10.0'
use_frameworks!
pod 'MarcoPolo'

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/HelioMesquita/MarcoPolo/.git", .branch("main"))
]

How to use

Before you starting using MarcoPolo you must configure some URLScheme to allow the deep-liking work.

First follow those steps in image. You can choose the name that you want.

Swiftmazing Logo

After configuring the deep-linking, you must create the main/principal coordinator to hold all features and implement it in your app delegate or scene delegate.

import MarcoPolo
import UIKit

class MainCoordinator: DeeplinkCoordinator {
  var viewControllers: [any DeeplinkViewController.Type] = [
    ViewController.self // First view controller when opens the app
  ]
  lazy var coordinators: [DeeplinkCoordinator] = [
    // All your features coordinators here
  ]
  var navigation: UINavigationController

  required init(navigation: UINavigationController) {
    self.navigation = navigation
  }

  func open(_ viewController: any DeeplinkViewController.Type, arguments: Any?) {
    let vc = viewController.init()
    navigation.pushViewController(vc, animated: true)
  }
}

Your view controller will appear like this

import MarcoPolo
import UIKit

class ViewController: UIViewController, DeeplinkViewController, DeeplinkOpener {
  typealias DeeplinkParameterReceiveType = String //Type of argument that deep-link will add in your class

  static var path: String = "main" // Deep-link path to find your class
}

Using SceneDelegate

import OSLog
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var coordinator = MainCoordinator(navigation: UINavigationController())
  var window: UIWindow?

  func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let firstUrl = URLContexts.first?.url else {
      return
    }
    if coordinator.canOpenURL(firstUrl) {
      coordinator.handleURL(firstUrl, arguments: UIApplication.shared.arguments)
    } else {
      os_log("Deeplink not found", log: OSLog.default, type: .error)
    }
  }

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }

    let window = UIWindow(windowScene: windowScene)

    coordinator.open(ViewController.self, arguments: nil)
    window.rootViewController = coordinator.navigation

    self.window = window
    window.makeKeyAndVisible()
  }
}

Using AppDelegate

import OSLog
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?
  var coordinator = MainCoordinator(navigation: UINavigationController())
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    window = UIWindow(frame: UIScreen.main.bounds)
    coordinator.open(ViewController.self, arguments: nil)
    window.rootViewController = coordinator.navigation
    self.window = window
    window.makeKeyAndVisible()
    return true
  }

  func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    if coordinator.canOpenURL(url) {
      coordinator.handleURL(url, arguments: UIApplication.shared.arguments)
      return true
    } else {
      os_log("Deeplink not found", log: OSLog.default, type: .error)
      return false
    }
}

Now everything is set up and you are ready to go

Just dont forget to add your new screen in the coordinator ๐Ÿ˜…

Contribute

We would love you for the contribution to MarcoPolo, check the LICENSE file for more info.

https://github.com/HelioMesquita/MarcoPolo

marcopolo's People

Contributors

heliomesquita avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.