问题描述
在我用 Viper 制作的项目中,ViewController 中的 Presenter 给出了一个 nil 错误。这是什么原因?我该如何解决这个问题?
应用委托
let wireframe = MovieWireframe()
let movies = wireframe.createMovieController()
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UINavigationController(rootViewController: movies)
window?.makeKeyAndVisible()
视图控制器
var presenter: IMoviePresenter? //Nil
override func viewDidLoad() {
super.viewDidLoad()
presenter?.startFetchingMovies() //Nil
}
主持人
此处的 StartFetchingMovies 不起作用,因为演示者为零。
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不是nil。
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) {
}
}
解决方法
ViewController 的初始化在 createMovieController 在这里的第一行和第二行之间被调用之前完成:
let wireframe = MovieWireframe()
let movies = wireframe.createMovieController()
在那段短暂的时间里,视图加载(由于创建线框)
var presenter: IMoviePresenter?
作为 nil(因此为什么暂时需要问号)并导致 viewDidLoad 被“过早地”调用(即在调用第二行之前)。因此,消除 2 部分构造,使其不会在 1) 没有 MovieController 的情况下零碎地完成,然后 2) 作为 MovieWireframe 构造之外的第二步完成。 1 部分结构不是 2 部分。