Swift 4中如何判断来源视图控制器?复用UserDataViewController问询
这问题我之前做项目时也碰到过,复用UserDataViewController来处理注册和资料更新,核心就是要明确当前的业务场景,给你几个Swift 4里实用的方案,按需选就行:
方案1:用枚举标记场景(最推荐)
这种方式最清晰,完全解耦来源控制器的类型,后期要加新场景(比如修改密码)也非常方便,是我平时用得最多的方式。
首先定义一个枚举来标记业务场景:
enum UserDataScene { case register case profileUpdate // 以后加新场景直接在这里加就行,比如case passwordChange }
然后在UserDataViewController里添加一个场景属性,跳转时传入对应的值:
class UserDataViewController: UIViewController { // 用隐式解包可选类型,确保跳转时一定会赋值 var currentScene: UserDataScene! // 比如提交按钮点击时,根据场景执行不同逻辑 @IBAction func submitButtonTapped(_ sender: UIButton) { switch currentScene { case .register: // 执行注册相关逻辑:调用注册接口、返回注册页面等 print("处理注册流程") navigationController?.popViewController(animated: true) case .profileUpdate: // 执行资料更新逻辑:调用更新接口、返回个人资料页等 print("处理资料更新流程") navigationController?.popViewController(animated: true) default: break } } }
跳转时给场景属性赋值:
// 从RegisterViewController跳转 let userDataVC = UserDataViewController() userDataVC.currentScene = .register navigationController?.pushViewController(userDataVC, animated: true) // 从ProfileViewController跳转 let userDataVC = UserDataViewController() userDataVC.currentScene = .profileUpdate navigationController?.pushViewController(userDataVC, animated: true)
方案2:直接判断来源控制器类型(快速实现)
如果你的项目逻辑简单,不想额外定义枚举,可以直接判断来源控制器的类型。不过这种方式耦合度高,以后来源控制器改名或者结构调整时,这里也要跟着改,适合小场景快速实现。
class UserDataViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 页面加载时判断来源 identifySourceViewController() } private func identifySourceViewController() { // 处理push过来的情况:取导航栈里的前一个控制器 if let viewControllers = navigationController?.viewControllers, viewControllers.count >= 2 { let previousVC = viewControllers[viewControllers.count - 2] if previousVC is RegisterViewController { print("来源是注册页面,准备处理注册逻辑") } else if previousVC is ProfileViewController { print("来源是个人资料页面,准备处理更新逻辑") } } // 处理present过来的情况:判断presentingViewController else if let presentingVC = presentingViewController { if presentingVC is RegisterViewController { print("来源是注册页面") } else if presentingVC is ProfileViewController { print("来源是个人资料页面") } } } }
方案3:闭包回调(适合需要反向传值的场景)
如果UserDataViewController收集完数据后,需要把数据回传给来源控制器,用闭包回调会很方便,同时也能附带场景信息。
// 先定义一个用户数据模型(假设你需要回传这类数据) struct UserData { let name: String let email: String } class UserDataViewController: UIViewController { // 定义闭包,参数是收集到的用户数据和当前场景 var onSubmit: ((UserData, UserDataScene) -> Void)? @IBAction func submitButtonTapped(_ sender: UIButton) { // 模拟收集到的用户数据 let collectedData = UserData(name: "Farid", email: "farid@example.com") // 确定当前场景 guard let viewControllers = navigationController?.viewControllers, viewControllers.count >= 2 else { return } let previousVC = viewControllers[viewControllers.count - 2] let scene: UserDataScene = previousVC is RegisterViewController ? .register : .profileUpdate // 调用闭包回传数据 onSubmit?(collectedData, scene) navigationController?.popViewController(animated: true) } }
跳转时设置闭包:
// 从RegisterViewController跳转 let userDataVC = UserDataViewController() userDataVC.onSubmit = { [weak self] userData, scene in guard let self = self else { return } // 这里处理注册逻辑,比如提交到服务器 self.completeRegistration(with: userData) } navigationController?.pushViewController(userDataVC, animated: true) // 从ProfileViewController跳转 let userDataVC = UserDataViewController() userDataVC.onSubmit = { [weak self] userData, scene in guard let self = self else { return } // 这里处理资料更新逻辑 self.updateUserProfile(with: userData) } navigationController?.pushViewController(userDataVC, animated: true)
内容的提问来源于stack exchange,提问作者Farid Valiyev
相关产品推荐
相关产品推荐

