Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can not send data to another module in VIPER

How can i send data from Module A to Module B in VIPER? I use router A, which has information for Module B, and try to send this information to view controller B or presenter B. What is the best way to do it?

like image 543
Yakimenko Aleksey Avatar asked Jul 18 '16 08:07

Yakimenko Aleksey


3 Answers

In that case my workflow is:

  1. Usually the user interface (view) in module A launches an event that triggers the module B.
  2. The event reaches the presenter in module A. The presenter knows it has to change module and notifies wireframe who knows how to make the change.
  3. The wireframe in module A notifies to wireframe in module B. In this call sends all data needed
  4. The wireframe in module B continues its normal execution, transferring the information to the presenter

wireframe in module A must know wireframe B

like image 119
David Avatar answered Nov 17 '22 02:11

David


Use delegates to send data between VIPER modules:

// 1. Declare which messages can be sent to the delegate

// ProductScreenDelegate.swift
protocol ProductScreenDelegate {
//Add arguments if you need to send some information
    func onProductScreenDismissed()
    func onProductSelected(_ product: Product?)
}

// 2. Call the delegate when you need to send him a message

// ProductPresenter.swift
class ProductPresenter {

    // MARK: Properties
    weak var view: ProductView?
    var router: ProductWireframe?
    var interactor: ProductUseCase?
    var delegate: ProductScreenDelegate?
}

extension ProductPresenter: ProductPresentation {

    //View tells Presenter that view disappeared
    func onViewDidDisappear() {

        //Presenter tells its delegate that the screen was dismissed
        delegate?.onProductScreenDismissed()
    }
}

// 3. Implement the delegate protocol to do something when you receive the message

// ScannerPresenter.swift
class ScannerPresenter: ProductScreenDelegate {

    //Presenter receives the message from the sender
    func onProductScreenDismissed() {

        //Presenter tells view what to do once product screen was dismissed
        view?.startScanning()
    }
    ...
}

// 4. Link the delegate from the Product presenter in order to proper initialize it

// File ScannerRouter.swift
class ProductRouter {

    static func setupModule(delegate: ProductScreenDelegate?) -> ProductViewController {
        ...
        let presenter = ScannerPresenter()

        presenter.view = view
        presenter.interactor = interactor
        presenter.router = router
        presenter.delegate = delegate // Add this line to link the delegate
        ...
        }
}

For more tips, check this post https://www.ckl.io/blog/best-practices-viper-architecture/

like image 5
Marcelo Gracietti Avatar answered Nov 17 '22 00:11

Marcelo Gracietti


Does wireframe have reference to presenter? This version of VIPER which i use

The router knows about another module and tells view to open it. Assembly combines all parts of module.

like image 3
Yakimenko Aleksey Avatar answered Nov 17 '22 01:11

Yakimenko Aleksey