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

Swift 4:如何根据选中选项让视图控制器加载不同UIView

用单个视图控制器加载不同自定义UIView的解决方案

看起来你已经搞定了菜单跳转和导航栏标题的部分,接下来只需要让selectionController根据选中的菜单选项加载对应的UIView就行,我给你两种可行的实现方式,按需选择:

方式一:用枚举匹配(类型安全,推荐)

首先把你的MenuOption改成枚举,这样能避免字符串拼写错误,扩展性也更好:

// 定义菜单选项枚举,对应你所有的视图选项
enum MenuOption: String, CaseIterable {
    case settings = "Settings"
    case profile = "Profile"
    case notifications = "Notifications"
    // 继续添加其他15+选项...
}

然后创建每个选项对应的自定义UIView,比如SettingsView:

class SettingsView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        // 这里写Settings视图的布局和逻辑
        backgroundColor = .white
        
        let titleLabel = UILabel()
        titleLabel.text = "Settings Page"
        titleLabel.font = UIFont.systemFont(ofSize: 24, weight: .bold)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        addSubview(titleLabel)
        
        // AutoLayout约束,让标题居中
        NSLayoutConstraint.activate([
            titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

接下来修改HomeController里的displayController方法,根据枚举值加载对应的View:

func displayController(menuOption: MenuOption) {
    let selectionController = UIViewController()
    selectionController.navigationItem.title = menuOption.rawValue
    selectionController.view.backgroundColor = .blue
    
    // 根据菜单选项创建对应的自定义View
    var contentView: UIView!
    switch menuOption {
    case .settings:
        contentView = SettingsView()
    case .profile:
        contentView = ProfileView() // 对应你的Profile视图
    case .notifications:
        contentView = NotificationsView() // 对应你的通知视图
    // 依次添加其他选项的匹配逻辑
    }
    
    // 将自定义View铺满selectionController的视图
    contentView.translatesAutoresizingMaskIntoConstraints = false
    selectionController.view.addSubview(contentView)
    NSLayoutConstraint.activate([
        contentView.topAnchor.constraint(equalTo: selectionController.view.topAnchor),
        contentView.leadingAnchor.constraint(equalTo: selectionController.view.leadingAnchor),
        contentView.trailingAnchor.constraint(equalTo: selectionController.view.trailingAnchor),
        contentView.bottomAnchor.constraint(equalTo: selectionController.view.bottomAnchor)
    ])
    
    navigationController?.navigationBar.tintColor = .white
    navigationController?.pushViewController(selectionController, animated: true)
}

方式二:给MenuOption绑定View类型(更简洁,扩展性强)

如果不想写长长的switch语句,可以给你的MenuOption结构体添加一个viewType属性,直接绑定对应的View类型:

struct MenuOption {
    let name: String
    let viewType: UIView.Type // 存储对应的View类型
}

// 初始化你的菜单选项数组时,直接绑定View
let menuOptions = [
    MenuOption(name: "Settings", viewType: SettingsView.self),
    MenuOption(name: "Profile", viewType: ProfileView.self),
    MenuOption(name: "Notifications", viewType: NotificationsView.self),
    // 其他选项...
]

然后修改displayController方法,直接通过viewType实例化View:

func displayController(menuOption: MenuOption) {
    let selectionController = UIViewController()
    selectionController.navigationItem.title = menuOption.name
    selectionController.view.backgroundColor = .blue
    
    // 直接实例化对应的View
    let contentView = menuOption.viewType.init(frame: selectionController.view.bounds)
    // 设置autoresizingMask让View自动适配控制器视图尺寸
    contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    selectionController.view.addSubview(contentView)
    
    navigationController?.navigationBar.tintColor = .white
    navigationController?.pushViewController(selectionController, animated: true)
}

注意事项

  • 每个自定义UIView要自己处理内部的布局和交互逻辑,比如按钮点击、表单输入等,这样代码职责更清晰
  • 如果需要和selectionController通信(比如View里的操作需要更新导航栏),可以通过代理模式或者闭包实现
  • 确保自定义View的布局适配不同屏幕尺寸,推荐用AutoLayout而不是固定frame

内容的提问来源于stack exchange,提问作者Chandler Long

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:35:52