zafarivaev / ReactiveCoordinator-Combine

Coordinator framework leveraging Combine

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ReactiveCoordinator

ReactiveCoordinator is a framework based on the Coordinator pattern. Implemented in Combine.

Requirements

  • iOS 14.0
  • Swift 5

How To Use

Inherit from ReactiveCoordinator in Coordinator subclasses:

final class FirstCoordinator: Coordinator<Void> {
    unowned let navigationController: UINavigationController
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    override func start() -> AnyPublisher<Void, Never> {
        
        let viewController = FirstViewController(
            coordinator: self
        )
        navigationController.pushViewController(
            viewController, 
            animated: false
        )
        
        return Empty(completeImmediately: false)
            .eraseToAnyPublisher()
    }
}

Replace Delegation with ReactiveCoordinator

In presented Coordinator:

enum ItemsCoordinationResult {
    case item(String)
}

final class ItemsCoordinator: Coordinator<ItemsCoordinationResult> {
    unowned let navigationController: UINavigationController
    public let coordinationResult = PassthroughSubject<ItemsCoordinationResult, Never>()
    
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    override func start() -> AnyPublisher<ItemsCoordinationResult, Never> {
        let viewController = ItemsViewController(coordinator: self)
        navigationController.present(viewController, animated: true, completion: nil)
        
        return coordinationResult.eraseToAnyPublisher()
    }
}

In presenting Coordinator:

final class FirstCoordinator: Coordinator<Void> {
    
    ...
    
    public func presentItems() -> AnyPublisher<ItemsCoordinationResult, Never> {
        let coordinator = ItemsCoordinator(
            navigationController: navigationController
        )
        
        return coordinate(to: coordinator)
            .handleEvents(receiveOutput: { [weak self] _ in
                self?.navigationController.dismiss(animated: true, completion: nil)
            })
            .eraseToAnyPublisher()
    }
}

In presenting Coordinator's view controller:

override func viewDidLoad() {
    actionButton
      .publisher(for: .touchUpInside)
      .flatMap { [unowned self] _ in
          self.coordinator.presentItems()
      }
      .sink { result in
          if case let .item(title) = result {
              print(title)
          }
      }
      .store(in: &cancellables)
}

License

ReactiveCoordinator is released under the MIT license. See LICENSE for details.

About

Coordinator framework leveraging Combine

License:MIT License


Languages

Language:Swift 100.0%