首页 > 解决方案 > 演示者在 VIPER 项目中给出零错误

问题描述

在我用 Viper 做的项目中,ViewController 中的 Presenter 给出了一个 nil 错误。这是什么原因?我该如何解决这个问题?

应用委托

let wireframe = MovieWireframe()
let movies = wireframe.createMovieController()
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UINavigationController(rootViewController: movies)
window?.makeKeyAndVisible()

视图控制器

Presenter here 给出了一个 nil 错误。

var presenter: IMoviePresenter? //Nil
   
override func viewDidLoad() {
  super.viewDidLoad()

  presenter?.startFetchingMovies() //Nil 
}

主持人

此处的 StartFetchingMovies 不起作用,因为 Presenter 为 nil。

class MoviePresenter: IMoviePresenter {
    
    var view: IMovieView?
    var interactor: IMovieInteractor
    var router: IMovieWireframe
    var movies: MoviesResult?
    
    init(view: IMovieView?, interactor: IMovieInteractor, router: IMovieWireframe) {
        self.view = view
        self.interactor = interactor
        self.router = router

    }
    

    func startFetchingMovies() {
        interactor.fetchMovies()

    }
    
    func showMovieController(navigationController: UINavigationController) {
        router.pushToMovieDetailScreen(navigationController: navigationController)
    }
}

extension MoviePresenter: IMovieInteractorDelegate {
    func movieInteractorDidSuccessToFetchMovies(movies: MoviesResult) {
        self.movies = movies
        view?.showMovie(movies: movies)
    }
    
    func movieInteractorDidFailToFetchMovies() {
        print("error")
    }
}

路由器

这里的 View.presenter 不是零。

class MovieWireframe: IMovieWireframe {
    
    func createMovieController() -> UIViewController {
        print("createMovieController")
        let view = MovieVC()
        let movieService = APIClient()
        let interactor = MovieInteractor(movieService: movieService)
        let presenter = MoviePresenter(
            view: view,
            interactor: interactor,
            router: self
        )
        
        view.presenter = presenter
        print("presenter: \(presenter)")
        interactor.delegate = presenter

        return view
    }
    
    func pushToMovieDetailScreen(navigationController: UINavigationController) {
        
        
    }
}

标签: iosswiftviper-architecture

解决方案


ViewController 的初始化在 createMovieController 在这里的第一行和第二行之间被调用之前完成:

let wireframe = MovieWireframe()
let movies = wireframe.createMovieController()

在这段短暂的时间里,视图加载(由于创建线框)

var presenter: IMoviePresenter?

为 nil (因此为什么暂时需要问号)并导致 viewDidLoad 被“过早”调用(即,在调用第二行之前)。因此,消除 2 部分构造,这样就不会在 1) 没有 MovieController 的情况下零碎完成,然后 2) 作为 MovieWireframe 构造之外的第二步完成。1 部分结构不是 2 部分。


推荐阅读