以编程方式创建Segue后,如何向第二个ViewController传递不同信息?
嘿,这个场景我太熟悉了——纯代码创建按钮和Segue的时候,没法像Storyboard里那样给Segue加标识符,确实会卡住一会儿。不过有几个实用的办法能解决,我给你捋一捋:
方法1:利用按钮Tag区分(最快捷)
这种方法不用额外写子类,靠按钮的tag属性来区分点击源,然后在Segue的准备方法里传递对应数据。
步骤:
- 创建按钮时给它们分配唯一的Tag,并绑定点击事件:
// 第一个按钮 let btn1 = UIButton(type: .system) btn1.setTitle("传递信息A", for: .normal) btn1.tag = 1 btn1.addTarget(self, action: #selector(onButtonTapped(_:)), for: .touchUpInside) btn1.frame = CGRect(x: 50, y: 200, width: 200, height: 44) view.addSubview(btn1) // 第二个按钮 let btn2 = UIButton(type: .system) btn2.setTitle("传递信息B", for: .normal) btn2.tag = 2 btn2.addTarget(self, action: #selector(onButtonTapped(_:)), for: .touchUpInside) btn2.frame = CGRect(x: 50, y: 260, width: 200, height: 44) view.addSubview(btn2)
- 点击事件里触发Segue,并把按钮作为
sender传递:
@objc func onButtonTapped(_ sender: UIButton) { // 编程创建Segue(如果没有从Storyboard拖的话) let destinationVC = SecondViewController() let segue = UIStoryboardSegue(source: self, destination: destinationVC) // 先执行准备逻辑,再触发Segue self.prepare(for: segue, sender: sender) segue.perform() }
- 在
prepare(for:sender:)里根据Tag判断,传递数据:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let targetVC = segue.destination as? SecondViewController, let tappedBtn = sender as? UIButton else { return } switch tappedBtn.tag { case 1: targetVC.receivedData = "这是按钮1带来的消息" case 2: targetVC.receivedData = "这是按钮2带来的消息" default: targetVC.receivedData = "默认消息" } }
(记得给SecondViewController加一个receivedData属性用来接收数据哦)
如果不想用Tag(毕竟Tag容易冲突、可读性差),可以给按钮加自定义属性,直接把要传递的数据存在按钮里。
步骤:
- 创建自定义Button子类:
class DataCarryingButton: UIButton { // 可以改成你需要的任意数据类型,比如模型对象 var messageToPass: String? }
- 创建按钮时直接赋值自定义数据:
let btnA = DataCarryingButton(type: .system) btnA.setTitle("发送专属消息A", for: .normal) btnA.messageToPass = "按钮A的私有消息" btnA.addTarget(self, action: #selector(onCustomBtnTapped(_:)), for: .touchUpInside) view.addSubview(btnA) let btnB = DataCarryingButton(type: .system) btnB.setTitle("发送专属消息B", for: .normal) btnB.messageToPass = "按钮B的私有消息" btnB.addTarget(self, action: #selector(onCustomBtnTapped(_:)), for: .touchUpInside) view.addSubview(btnB)
- 点击处理和数据传递:
@objc func onCustomBtnTapped(_ sender: DataCarryingButton) { let targetVC = SecondViewController() let segue = UIStoryboardSegue(source: self, destination: targetVC) prepare(for: segue, sender: sender) segue.perform() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let targetVC = segue.destination as? SecondViewController, let tappedBtn = sender as? DataCarryingButton else { return } targetVC.receivedData = tappedBtn.messageToPass ?? "默认消息" }
方法3:直接实例化目标VC(最灵活)
其实纯代码开发的时候,我个人更推荐这种方法——完全跳过Segue,直接创建目标ViewController,设置数据后导航过去,少了很多Segue的约束:
// 先把按钮存为实例变量,方便判断点击源 var btn1: UIButton! var btn2: UIButton! override func viewDidLoad() { super.viewDidLoad() btn1 = UIButton(type: .system) btn1.setTitle("直接跳转传信息1", for: .normal) btn1.addTarget(self, action: #selector(onDirectJumpTapped(_:)), for: .touchUpInside) view.addSubview(btn1) btn2 = UIButton(type: .system) btn2.setTitle("直接跳转传信息2", for: .normal) btn2.addTarget(self, action: #selector(onDirectJumpTapped(_:)), for: .touchUpInside) view.addSubview(btn2) } @objc func onDirectJumpTapped(_ sender: UIButton) { let targetVC = SecondViewController() // 根据点击的按钮设置数据 if sender === btn1 { targetVC.receivedData = "直接跳转:按钮1的消息" } else if sender === btn2 { targetVC.receivedData = "直接跳转:按钮2的消息" } // 如果是导航控制器环境,push过去 navigationController?.pushViewController(targetVC, animated: true) // 如果是模态展示,用这个: // present(targetVC, animated: true) }
这种方式代码更直观,不用管Segue的标识符或者准备方法,完全由你控制流程,特别适合纯代码搭建的界面。
内容的提问来源于stack exchange,提问作者Aurel Calin Muth
相关产品推荐
相关产品推荐

