使用VIP体系结构Swift创建配置器的正确方法

发布于 2025-02-07 12:12:53 字数 3637 浏览 1 评论 0 原文

我尝试将VIP体系结构介绍给我的项目,并且不完全理解我发现的示例,我遵循此信息 https://www.netguru.com/blog/clean-swift-ios-architecture-pattern ,并检查我对背后的想法感到困惑的源代码,这就是创建此组件或如何构建此组件的方式的可重复使用的想法? 示例:

// 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
    }
}

就我而言,我使用一个简单的小结构,不知道这是正确的方法,当我复制这个想法并尝试在项目中实现它时,这是行不通的。我还将项目的源代码附加了Google 我的例子:

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
        
    }
}

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
        
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心欲静而疯不止 2025-02-14 12:12:53

我一直在研究这个问题,就像假设可以说,这是创建用于配置的静态功能的最方便的方法,我想这是一种经典的方法,问题中描述的所有信息都是生产的一种变化我在文章中发现的一种“配置器”对我来说很复杂,而且静态功能是经典的。这些想法基于检查一些具有VIP和VIPER架构的项目,如果您还有其他想法或想法,我将不胜感激。我使用

P.S.我在项目中没有删除的一个小代码也包含一个依赖注入/反转的示例,但我想对某人来说很有趣,这些是< swift; amp& amp; Aleksey Chechil>
我的代码:

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
    }
}

场景委托:

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
    }

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
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文