The correct way of creating a configurator using VIP architecture Swift

875 Views Asked by At

I try to introduce VIP architecture to my project and do not fully understand the examples that I find, I follow this info https://www.netguru.com/blog/clean-swift-ios-architecture-pattern, and examine the source code inside I am confused about the idea behind, this is the reusable idea of a creating this component or one of the way how to build this component? Example:

// Scene Factory

protocol SceneFactory {
    var configurator: LoginSceneConfigurator! { get set }
    func makeLoginScene() -> UIViewController
}

final class DefaultSceneFactory: SceneFactory {
    var configurator: LoginSceneConfigurator!
    
    func makeLoginScene() -> UIViewController {
        let vc = LoginSceneViewController()
        return configurator.configured(vc)
    }

// Configurator

protocol LoginSceneConfigurator {
    func configured(_ vc: LoginSceneViewController) -> LoginSceneViewController
}

final class DefaultLoginSceneConfigurator: LoginSceneConfigurator {
    private var sceneFactory: SceneFactory
    
    init(sceneFactory: SceneFactory) {
        self.sceneFactory = sceneFactory
    }
    
    @discardableResult
    func configured(_ vc: LoginSceneViewController) -> LoginSceneViewController {
        sceneFactory.configurator = self
        let service = DefaultAuthService(
            networkManager: DefaultNetworkManager(session: MockNetworkSession())
        )
        let authWorker = LoginSceneAuthWorker(service: service)
        let interactor = LoginSceneInteractor()
        let presenter = LoginScenePresenter()
        let router = LoginSceneRouter(sceneFactory: sceneFactory)
        router.source = vc
        presenter.viewController = vc
        interactor.presenter = presenter
        interactor.authWorker = authWorker
        vc.interactor = interactor
        vc.router = router
        return vc
    }
}

In my case, I use a simple little construction and don't know if this is the correct way or not, when I copy the idea and try to implement it in my project, this does not work. I have also attached the source code of my project on google https://drive.google.com/file/d/1DcTxDXNl8idp2C3HLs5ggixdRVTE1UGY/view?usp=sharing My example:

protocol HomeViewProtocol {
    func reloadView(_ bucketLists: [TestData])
    func showSearchResult(result: String)
    func progressState()
}

extension HomeViewController: HomeViewProtocol {
    func progressState() {
        views?.loader.startAnimating()
    }
    
    func showSearchResult(result: String) {
        router?.showSearchMsg(result)
        views?.loader.stopAnimating()
    }
    
    func reloadView(_ bucketLists: [TestData]) {
        self.bucketLists = bucketLists
        views?.label.text = bucketLists.last?.title
    }
}

class HomeViewController: UIViewController {
    
    private var bucketLists: [TestData] = []
    
    var interactor: HomeInteractorProtocol?
    var router: HomeViewControllerRouter?
    var views: HomeViewContollerViews?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configurator()
        
        views?.setupUI()
        views?.setupConstraint()
        views?.setupNavigationControllerElemenst()
        
    }
    
    private func configurator() {
        let searchWorker: HomeViewControllerSearchWorkerProtocol = HomeViewControllerSearchWorker()
        
        var presenter: HomePresenterProtocol = HomePresenter()
        presenter.viewController = self
        
        interactor = HomeInteractor()
        interactor?.presenter = presenter
        interactor?.searchWorker = searchWorker
        
        router = HomeViewControllerRouter()
        router?.source = self
        views = HomeViewContollerViews()
        views?.source = self
        
    }
}
1

There are 1 best solutions below

0
On

I have continued researching this question, and like assumption can say that the most convenient way this is to create a static func for configuration, I guess this is a classic approach, all info that is described in the question is the kind of variation to producing a "Configurator", an approach that I found in the article, was to complex for me, and static func it's classic. These thoughts are based on examining a few projects with VIP and VIPER architecture, if you have any other ideas or thoughts, I will be appreciated them. My project with VIP architecture and the project that I found with VIPER architecture will be attached, If you only have been begun to familiarize yourself with this architecture, these projects will be interesting for you

P.S. A little code that I didn't delete in my project also contained an example of Dependency injection/inversion, but I guess will be interesting for someone, these are the example by <Swift Book & Aleksey Chechil> My code:

class HomeVCConfigurator {
    class func configure() -> HomeViewController {
        let viewController = HomeViewController()
        
        let searchWorker: HomeViewControllerSearchWorkerProtocol = HomeViewControllerSearchWorker()
        
        var presenter: HomePresenterProtocol = HomePresenter()
        presenter.viewController = viewController
        
        viewController.interactor = HomeInteractor()
        viewController.interactor?.presenter = presenter
        viewController.interactor?.searchWorker = searchWorker
        
        viewController.router = HomeViewControllerRouter()
        viewController.router?.source = viewController
        viewController.views = HomeViewContollerViews()
        viewController.views?.source = viewController
        
        return viewController
    }
}

Scene Delegate:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let windowScene = (scene as? UIWindowScene) else { return }
        
        let window = UIWindow(windowScene: windowScene)
        let vc = HomeVCConfigurator.configure()
        vc.id = 5
        let navigatioContoller = UINavigationController(rootViewController: vc)
        window.rootViewController = navigatioContoller// Your initial view controller.
        window.makeKeyAndVisible()
        self.window = window
    }