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

如何以编程方式设置Storyboard ID或正确配置Delegate实现传值

解决Delegate配置与Storyboard ID的问题

首先,我先帮你理清几个关键问题,然后给出正确的代码示例:

一、纯代码VC没有Storyboard ID

你的ProgramaticVC是纯代码实现的,并没有添加到Storyboard画布中,所以它没有Storyboard ID,也无法通过UIStoryboard.instantiateViewController来创建它的实例。你在InterfaceBuilderVC里尝试实例化ProgramaticVC的代码是无效的,因为这个VC根本不在Storyboard里。

二、正确配置正向传值(ProgramaticVC → InterfaceBuilderVC)

你当前的需求是从纯代码VC向IB创建的VC传递数据,这种正向传值用直接赋值属性的方式比Delegate更简单直接。如果一定要用Delegate,我也会给出对应的配置方法。

方法1:直接赋值属性(推荐)

1. 修改InterfaceBuilderVC代码

给它添加用于接收数据的属性,并在viewDidLoad中更新UI:

class InterfaceBuilderVC: UIViewController {
    @IBOutlet weak var areaLabel: UILabel!
    @IBOutlet weak var locationLabel: UILabel!
    
    // 添加接收数据的属性
    var receivedArea: String?
    var receivedLocation: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 用接收的属性更新UI
        areaLabel.text = receivedArea
        locationLabel.text = receivedLocation
    }
}

2. 修改ProgramaticVC代码

实例化InterfaceBuilderVC后,直接给属性赋值再跳转:

class ProgramaticVC: UIViewController {
    // 假设这是触发跳转的方法
    func passDataAndJump() {
        let area = "你的区域数据"
        let location = "你的位置数据"
        
        // 实例化InterfaceBuilderVC(注意这里要先给IB里的VC设置Storyboard ID)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        guard let interfaceBuilderVC = storyboard.instantiateViewController(withIdentifier: "InterfaceBuilderVC") as? InterfaceBuilderVC else {
            fatalError("找不到InterfaceBuilderVC,请检查Storyboard ID是否正确")
        }
        
        // 直接给属性赋值
        interfaceBuilderVC.receivedArea = area
        interfaceBuilderVC.receivedLocation = location
        
        // 执行跳转
        show(interfaceBuilderVC, sender: nil)
    }
}

方法2:用Delegate实现(适合需要回调的场景)

如果你的场景需要在数据传递后触发一些回调,或者坚持用Delegate,按以下步骤配置:

1. 定义符合规范的Delegate协议

// 协议继承AnyObject,用weak避免循环引用
protocol DataPassable: AnyObject {
    func passData(_ area: String, _ location: String)
}

2. 修正ProgramaticVC的代码

在实例化InterfaceBuilderVC后,将其设置为当前VC的delegate,再调用Delegate方法:

class ProgramaticVC: UIViewController {
    weak var delegate: DataPassable?
    
    func passDataAndJump() {
        let area = "你的区域数据"
        let location = "你的位置数据"
        
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        guard let interfaceBuilderVC = storyboard.instantiateViewController(withIdentifier: "InterfaceBuilderVC") as? InterfaceBuilderVC else {
            fatalError("找不到InterfaceBuilderVC")
        }
        
        // 设置delegate为InterfaceBuilderVC实例
        self.delegate = interfaceBuilderVC
        // 调用Delegate方法传递数据
        self.delegate?.passData(area, location)
        
        show(interfaceBuilderVC, sender: nil)
    }
}

3. 让InterfaceBuilderVC遵守协议并实现方法

class InterfaceBuilderVC: UIViewController, DataPassable {
    @IBOutlet weak var areaLabel: UILabel!
    @IBOutlet weak var locationLabel: UILabel!
    
    // 实现Delegate方法
    func passData(_ area: String, _ location: String) {
        areaLabel.text = area
        locationLabel.text = location
    }
}

三、给IB创建的VC设置Storyboard ID

你需要给InterfaceBuilderVC设置Storyboard ID,这样才能通过代码实例化它:

  1. 打开Main.storyboard
  2. 在画布上选中InterfaceBuilderVC
  3. 打开右侧的Identity Inspector(第三个标签,图标是身份证)
  4. 在Storyboard ID字段输入InterfaceBuilderVC(和你代码里的标识符一致)
  5. 确保勾选Use Storyboard ID

补充:如果需要反向传值(InterfaceBuilderVC → ProgramaticVC)

如果之后你需要从IB的VC向纯代码VC传数据,不要用Delegate去实例化新的ProgramaticVC,而是通过以下方式:

  1. 在InterfaceBuilderVC中添加一个弱引用属性:weak var dataDelegate: DataPassable?
  2. 在ProgramaticVC跳转时设置:interfaceBuilderVC.dataDelegate = self
  3. 让ProgramaticVC遵守DataPassable协议并实现方法,这样InterfaceBuilderVC就能调用dataDelegate?.passData(...)来传数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:57:49