Swift中基于工厂模式合并电影详情与相似影片视图的问题
合并电影详情与相似影片视图的可行方案
方案一:重构主视图控制器,直接管理两个子视图
这种方式无需使用容器控制器,直接在MovieDetailsDisplayViewController中嵌入两个业务子视图,通过ViewModel状态控制内容更新与视图显示:
- 在
MovieDetailsDisplayViewController中定义两个子视图属性,比如movieDetailsView(原详情视图)和similarMoviesView(原相似影片视图),确保它们初始化时已完成样式搭建。 - 重写
viewDidLoad,关闭两个子视图的translatesAutoresizingMaskIntoConstraints,将其添加到主视图后设置约束:把详情视图放在顶部,相似影片视图接在详情视图底部,铺满屏幕宽度,底部贴合安全区。 - 初始状态下隐藏相似影片视图,当ViewModel返回对应状态时,更新子视图内容并设置为显示。
代码示例:
// MovieDetailsDisplayViewController 内部实现 private let movieDetailsView = MovieDetailsView() private let similarMoviesView = SimilarMoviesView() override func viewDidLoad() { super.viewDidLoad() setupSubviews() } private func setupSubviews() { // 添加子视图并关闭自动约束 [movieDetailsView, similarMoviesView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false view.addSubview($0) } // 设置布局约束 NSLayoutConstraint.activate([ movieDetailsView.leadingAnchor.constraint(equalTo: view.leadingAnchor), movieDetailsView.trailingAnchor.constraint(equalTo: view.trailingAnchor), movieDetailsView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), similarMoviesView.leadingAnchor.constraint(equalTo: view.leadingAnchor), similarMoviesView.trailingAnchor.constraint(equalTo: view.trailingAnchor), similarMoviesView.topAnchor.constraint(equalTo: movieDetailsView.bottomAnchor), similarMoviesView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) // 初始隐藏相似影片视图 similarMoviesView.isHidden = true } // 响应ViewModel状态的方法 func handleMovieDetailsLoaded(_ details: MovieDetails) { movieDetailsView.configure(with: details) movieDetailsView.isHidden = false } func handleSimilarMoviesLoaded(_ movies: [Movie]) { similarMoviesView.configure(with: movies) similarMoviesView.isHidden = false }
方案二:修正容器视图控制器的实现
如果之前用容器控制器出问题,大概率是子控制器生命周期或约束配置错误,按以下步骤修正:
- 在
MovieDetailsDisplayViewController中定义两个子控制器:movieDetailsVC(原详情页控制器)和similarMoviesVC(原相似影片页控制器)。 - 在
viewDidLoad中,将两个子控制器添加为当前控制器的子控制器,同时将它们的view添加到主视图,务必调用addChild、didMove(toParent:)方法保证生命周期正确。 - 给两个子控制器的view设置和方案一相同的布局约束,初始隐藏相似影片控制器的view,收到对应状态时更新内容并显示。
代码示例:
// MovieDetailsDisplayViewController 内部实现 private let movieDetailsVC = MovieDetailsViewController() private let similarMoviesVC = SimilarMoviesViewController() override func viewDidLoad() { super.viewDidLoad() setupChildViewControllers() } private func setupChildViewControllers() { // 添加电影详情子控制器 addChild(movieDetailsVC) movieDetailsVC.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(movieDetailsVC.view) movieDetailsVC.didMove(toParent: self) // 添加相似影片子控制器 addChild(similarMoviesVC) similarMoviesVC.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(similarMoviesVC.view) similarMoviesVC.didMove(toParent: self) // 设置布局约束 NSLayoutConstraint.activate([ movieDetailsVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), movieDetailsVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), movieDetailsVC.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), similarMoviesVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), similarMoviesVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), similarMoviesVC.view.topAnchor.constraint(equalTo: movieDetailsVC.view.bottomAnchor), similarMoviesVC.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) similarMoviesVC.view.isHidden = true } // 响应ViewModel状态更新相似影片 func handleSimilarMoviesLoaded(_ movies: [Movie]) { similarMoviesVC.updateContent(with: movies) similarMoviesVC.view.isHidden = false }
方案三:调整ViewModel状态结构,统一驱动视图
修改ViewModel的状态定义,将电影详情和相似影片数据合并到一个状态中,减少控制器的状态响应逻辑:
- 重构
MoviesDetailsViewModel的状态枚举,新增包含详情和相似影片的联合状态,或者在现有loaded状态中加入相似影片的可选字段:
enum MovieDetailsState { case loading case loaded(details: MovieDetails, similarMovies: [Movie]?) case error(Error) }
- 控制器只需监听这个合并后的状态,收到
loaded状态时,先配置详情视图,若存在相似影片数据则配置并显示相似视图,避免多次状态切换的逻辑分支。
内容的提问来源于stack exchange,提问作者user23454452
相关产品推荐
相关产品推荐

