Swift中无Segue/导航栏时多视图控制器间传值方案问询
Swift无Segue、无导航栏多视图控制器传值解决方案
嘿,我来帮你搞定这个传值难题!你之前用全局变量没拿到更新值,大概率是全局变量的使用方式出了问题——比如不小心创建了多个实例,或者变量的作用域没处理好。针对你这种5个视图控制器逐步添加变量,最后汇总展示的场景,用单例数据模型统一管理所有状态是最省心的方案,下面给你一步步拆解实现:
一、先搞个单例数据模型,存所有要传的变量
新建一个Swift文件,比如叫UserDataModel.swift,把所有需要传递的变量都放在这里,而且要确保这个模型在整个App里只有一个实例(单例模式),这样所有VC操作的都是同一个数据源,数据肯定是最新的:
import Foundation class UserDataModel { // 全局唯一的单例实例,所有VC都用这个 static let shared = UserDataModel() // 这里根据你的需求加变量就行,每个VC对应自己的1-2个 var vc1Text: String? // VC1要传的文本 var vc1Count: Int? // VC1要传的数字 var vc2IsEnabled: Bool? // VC2要传的布尔值 var vc3Score: Double? // VC3要传的分数 var vc3Tags: [String]? // VC3要传的标签数组 var vc4SelectDate: Date? // VC4要传的日期 var vc5Remark: String? // VC5要传的备注 // 私有初始化方法,防止外部随便创建新实例 private init() {} }
二、每个视图控制器里更新对应变量
比如在第一个VC(VC1)里,当用户完成操作需要保存数据时,直接修改单例里的变量就行,跳转的时候直接present新VC(因为你不用Segue和导航栏):
// VC1里的按钮点击事件,保存数据 @IBAction func saveVC1Data(_ sender: UIButton) { // 拿到单例实例,修改对应变量 let dataModel = UserDataModel.shared dataModel.vc1Text = "用户在VC1输入的内容" dataModel.vc1Count = 88 } // 跳转到VC2的按钮事件 @IBAction func jumpToVC2(_ sender: UIButton) { let vc2 = VC2() present(vc2, animated: true) }
同理,VC2、VC3这些控制器也这么干,只需要修改自己对应的变量就行:
// VC2里保存数据的操作 @IBAction func saveVC2Data(_ sender: UIButton) { UserDataModel.shared.vc2IsEnabled = true } // 跳转到VC3 @IBAction func jumpToVC3(_ sender: UIButton) { let vc3 = VC3() present(vc3, animated: true) }
三、最后一个VC直接读取所有数据展示
到了最后一个VC(比如VC5),你直接从单例里把所有变量拿出来,展示到UI上就完事了:
override func viewDidLoad() { super.viewDidLoad() let dataModel = UserDataModel.shared // 把数据展示到对应的Label或者其他控件上 vc1TextLabel.text = dataModel.vc1Text ?? "未获取到VC1数据" vc1CountLabel.text = "\(dataModel.vc1Count ?? 0)" vc2StatusLabel.text = dataModel.vc2IsEnabled ?? false ? "已开启" : "未开启" // 其他VC的变量也这么处理... }
四、额外的小提醒
- 线程安全:如果你的App涉及多线程操作这些变量(比如后台请求完更新数据),可以给模型加个串行队列保护,避免数据混乱:
class UserDataModel { static let shared = UserDataModel() private let syncQueue = DispatchQueue(label: "com.yourapp.UserDataModel.sync") private var _vc1Text: String? var vc1Text: String? { get { return syncQueue.sync { _vc1Text } } set { syncQueue.async { self._vc1Text = newValue } } } // 其他变量也按这个格式写... private init() {} }
- 数据重置:如果用户完成一次流程后,需要清空所有数据避免影响下一次操作,可以给模型加个重置方法:
// 在UserDataModel里加重置方法 func resetAllData() { vc1Text = nil vc1Count = nil vc2IsEnabled = nil // 把所有变量都重置为nil或者初始值 } // 在最后一个VC的返回按钮里调用 @IBAction func finishAndReset(_ sender: UIButton) { UserDataModel.shared.resetAllData() dismiss(animated: true) }
可选的替代方案(不推荐给你的场景)
如果你不想用单例,也可以用闭包链式传值,但5个VC的话闭包会嵌套得很深,代码会变得乱糟糟的,维护起来很头疼,所以还是单例最适合你的需求。
内容的提问来源于stack exchange,提问作者Matthew Kaplan
相关产品推荐
相关产品推荐

