You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 09:02:46