Swift4中实现不同视图控制器间的数字加减问题求助
Hey Tommy, 别着急!我刚啃Swift的时候也被跨页面传值折腾过好几天,咱们一步步把这个问题解决掉~
你的需求核心是从4个子视图控制器把输入的数字传回主控制器,然后在主控制器的标签里计算并显示加减结果,下面给你两种适合Swift 4的实现方案,都是新手容易上手的:
方案一:用闭包反向传值(简单直观,推荐新手先试这个)
闭包是Swift里很灵活的传值方式,特别适合这种从子页面回传数据的场景。
步骤1:给子视图控制器添加闭包属性
以其中一个子VC(比如叫FirstInputVC)为例,代码如下:
import UIKit class FirstInputVC: UIViewController { // 先把Storyboard里的文本框关联到这里 @IBOutlet weak var numberTextField: UITextField! // 定义闭包,用来传递输入的数字(可选类型,处理空输入的情况) var onNumberInput: ((Double?) -> Void)? // 当页面即将消失时(比如点导航栏返回),触发闭包传值 override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) let inputNumber = Double(numberTextField.text ?? "") onNumberInput?(inputNumber) } // 如果是自定义的返回按钮,点击事件里也可以这么写 @IBAction func backButtonTapped(_ sender: UIButton) { let inputNumber = Double(numberTextField.text ?? "") onNumberInput?(inputNumber) navigationController?.popViewController(animated: true) } }
其他3个子VC的代码和这个几乎一样,只需要改类名就行。
步骤2:主控制器接收闭包传值并计算结果
主控制器(比如叫MainVC)里保存4个输入的数字,每次收到新数字就更新结果:
import UIKit class MainVC: UIViewController { // 保存4个输入的数字,默认值设为0避免空值问题 var num1: Double = 0 var num2: Double = 0 var num3: Double = 0 var num4: Double = 0 // 关联Storyboard里的结果标签 @IBOutlet weak var resultLabel: UILabel! // 跳转到第一个子VC的按钮点击事件 @IBAction func goToFirstInput(_ sender: UIButton) { guard let vc = storyboard?.instantiateViewController(withIdentifier: "FirstInputVC") as? FirstInputVC else { return } // 设置闭包,接收传回来的数字并更新 vc.onNumberInput = { [weak self] number in self?.num1 = number ?? 0 self?.calculateAndShowResult() } navigationController?.pushViewController(vc, animated: true) } // 另外3个按钮的点击事件,只需要把num1换成num2/num3/num4,对应子VC类名改对就行 @IBAction func goToSecondInput(_ sender: UIButton) { guard let vc = storyboard?.instantiateViewController(withIdentifier: "SecondInputVC") as? SecondInputVC else { return } vc.onNumberInput = { [weak self] number in self?.num2 = number ?? 0 self?.calculateAndShowResult() } navigationController?.pushViewController(vc, animated: true) } // 计算并更新结果的方法,这里默认是num1+num2-num3+num4,你可以根据需求改运算逻辑 private func calculateAndShowResult() { let finalResult = num1 + num2 - num3 + num4 resultLabel.text = String(format: "运算结果: %.2f", finalResult) } }
方案二:用代理模式(适合更复杂的页面交互场景)
如果之后你的APP要扩展更多交互逻辑,代理模式会更清晰。
步骤1:定义代理协议
在子VC的代码上方先写协议:
import UIKit // 定义代理协议,规定传值的方法 protocol NumberInputDelegate: AnyObject { func didInputNumber(_ number: Double?, from vc: UIViewController) } class FirstInputVC: UIViewController { @IBOutlet weak var numberTextField: UITextField! // 代理属性,必须用weak避免循环引用 weak var delegate: NumberInputDelegate? override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) let inputNumber = Double(numberTextField.text ?? "") delegate?.didInputNumber(inputNumber, from: self) } }
步骤2:主控制器遵守代理协议
import UIKit // 让主VC遵守代理协议 class MainVC: UIViewController, NumberInputDelegate { var num1: Double = 0 var num2: Double = 0 var num3: Double = 0 var num4: Double = 0 @IBOutlet weak var resultLabel: UILabel! @IBAction func goToFirstInput(_ sender: UIButton) { guard let vc = storyboard?.instantiateViewController(withIdentifier: "FirstInputVC") as? FirstInputVC else { return } // 设置代理为当前主VC vc.delegate = self navigationController?.pushViewController(vc, animated: true) } // 实现代理方法,判断是哪个子VC传回来的数字 func didInputNumber(_ number: Double?, from vc: UIViewController) { let inputNum = number ?? 0 switch vc { case is FirstInputVC: num1 = inputNum case is SecondInputVC: num2 = inputNum case is ThirdInputVC: num3 = inputNum case is FourthInputVC: num4 = inputNum default: break } calculateAndShowResult() } private func calculateAndShowResult() { let finalResult = num1 + num2 - num3 + num4 resultLabel.text = String(format: "运算结果: %.2f", finalResult) } }
新手注意事项
- 确保每个子VC在Storyboard里的Storyboard ID和代码里的
instantiateViewController(withIdentifier:)参数一致; - 用
[weak self]是为了避免循环引用,防止内存泄漏,这个是Swift里必须注意的点; - 如果不用导航控制器,而是用
present弹出子VC,返回时记得调用dismiss(animated:completion:),传值逻辑是一样的; - 如果需要整数运算,把
Double换成Int就行。
这样调整后,你就能在主页面实时看到四个输入数字的运算结果啦~
内容的提问来源于stack exchange,提问作者TommyXC
相关产品推荐
相关产品推荐

