Swift 4中如何从ViewController传数据至另一个ViewController再到TabBar
没问题,我帮你把Swift 4里从登录页到目标VC再到TabBar的完整数据传递流程捋清楚,结合你给出的代码片段补全实现:
1. 先补全LoginViewController的登录成功跳转逻辑
首先把你未完成的登录按钮事件代码补全,登录成功后拿到loggedUser,直接把数据传递给下一个页面(比如叫HomeViewController):
@IBAction func btnLoginPressed(_ sender: Any) { if self.textFieldLogin.text?.isEmpty ?? true || self.textFieldPassword.text?.isEmpty ?? true { self.errorLoginMessage(txt: "Uzupełnij wszystkie pola!!", title: "Błąd") } else { // 补全登录请求逻辑,假设checkUsersLogin是带闭包的异步请求 cms.checkUsersLogin(login: self.textFieldLogin.text!, password: self.textFieldPassword.text!) { [weak self] result in guard let self = self else { return } switch result { case .success(let user): self.loggedUser = user // 登录成功后跳转到HomeVC并传递数据 self.navigateToHomeVC() case .failure(let error): self.errorLoginMessage(txt: error.localizedDescription, title: "Błąd logowania") } } } } // 封装跳转逻辑,传递loggedUser给HomeVC private func navigateToHomeVC() { // 从Storyboard获取目标VC(记得给HomeVC设置storyboardID) guard let homeVC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return } // 直接赋值传递用户数据 homeVC.loggedUser = self.loggedUser // 用导航控制器push跳转(如果是present跳转就换成present方法) self.navigationController?.pushViewController(homeVC, animated: true) }
2. 从HomeViewController传递数据到TabBarController的子VC
接下来要把数据传到TabBar里的页面,建议先给TabBarController写一个子类,统一管理数据传递:
步骤2.1 定义TabBar子类和数据传递协议
// 自定义TabBarController子类 class AppTabBarController: UITabBarController { var loggedUser: LoginUser? { didSet { // 数据赋值后自动传递给所有子VC passUserToChildVCs() } } private func passUserToChildVCs() { guard let user = loggedUser else { return } // 遍历TabBar的所有子页面 viewControllers?.forEach { vc in // 如果子VC是导航控制器,需要取它的根VC if let navVC = vc as? UINavigationController { if let userAwareVC = navVC.topViewController as? UserAware { userAwareVC.loggedUser = user } } else if let userAwareVC = vc as? UserAware { userAwareVC.loggedUser = user } } } } // 定义协议,让需要接收用户数据的VC遵守 protocol UserAware: AnyObject { var loggedUser: LoginUser? { get set } }
步骤2.2 HomeVC里跳转到TabBar并传递数据
// HomeViewController里的跳转方法(比如点击进入TabBar的按钮事件) @IBAction func enterTabBarPressed(_ sender: Any) { guard let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: "AppTabBarController") as? AppTabBarController else { return } // 把用户数据传递给TabBarVC tabBarVC.loggedUser = self.loggedUser // 设置TabBar为根页面(或者用push/present,根据你的需求) self.navigationController?.setViewControllers([tabBarVC], animated: true) }
步骤2.3 让TabBar的子VC遵守协议接收数据
比如TabBar里的个人中心页面:
class ProfileViewController: UIViewController, UserAware { var loggedUser: LoginUser? override func viewDidLoad() { super.viewDidLoad() // 在这里使用用户数据更新UI if let user = loggedUser { print("当前登录用户:\(user.login)") // 比如设置用户名标签 // userNameLabel.text = user.login } } }
3. 可选的其他传递方式
如果不想用直接赋值的方式,还有两种常用方案:
方式一:闭包传递(适合灵活的场景)
在HomeVC里定义闭包,跳转时触发传递:
// HomeViewController var onUserPassed: ((LoginUser?) -> Void)? // 跳转按钮事件 @IBAction func enterTabBarPressed(_ sender: Any) { onUserPassed?(loggedUser) // 执行跳转... } // 在LoginVC跳转HomeVC时设置闭包 private func navigateToHomeVC() { guard let homeVC = self.storyboard?.instantiateViewController(withIdentifier: "HomeViewController") as? HomeViewController else { return } homeVC.loggedUser = self.loggedUser homeVC.onUserPassed = { [weak self] user in guard let tabBarVC = self?.storyboard?.instantiateViewController(withIdentifier: "AppTabBarController") as? AppTabBarController else { return } tabBarVC.loggedUser = user self?.navigationController?.setViewControllers([tabBarVC], animated: true) } self.navigationController?.pushViewController(homeVC, animated: true) }
方式二:NotificationCenter(适合跨多层级传递)
登录成功后发送通知,TabBar的子VC监听接收:
// LoginVC登录成功时发送通知 case .success(let user): self.loggedUser = user NotificationCenter.default.post(name: NSNotification.Name("UserLoggedIn"), object: user) self.navigateToHomeVC() // TabBar子VC里监听通知 class ProfileViewController: UIViewController { var loggedUser: LoginUser? override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(handleUserLogin(_:)), name: NSNotification.Name("UserLoggedIn"), object: nil) } @objc private func handleUserLogin(_ notification: Notification) { if let user = notification.object as? LoginUser { self.loggedUser = user // 更新UI } } deinit { // 记得移除监听,避免内存泄漏 NotificationCenter.default.removeObserver(self) } }
注意事项
- Swift 4里用闭包时一定要加
[weak self],避免循环引用导致内存泄漏 - 如果用Storyboard的segue跳转,可以在
prepare(for:sender:)方法里传递数据,逻辑和手动跳转一致 - 用协议的方式统一处理TabBar子VC的数据接收,扩展性更强,新增页面时只要遵守协议就行
内容的提问来源于stack exchange,提问作者Łukasz Betta
相关产品推荐
相关产品推荐

