如何控制Storyboard Segue?登录验证前置跳转问题
我帮你搞定这个问题!问题出在你直接把按钮和Segue绑定了——系统会在点击按钮的瞬间就触发跳转,根本没给你留时间做网络请求和判断的机会。下面给你两种靠谱的解决方案,推荐第一种,更直观可控:
解决方案一:手动触发Segue(推荐)
这是最清晰的方式,把Segue的触发权完全拿到代码里:
- 第一步:打开Storyboard,删掉你原来从登录按钮直接拖到目标视图的Segue。
- 第二步:从当前视图控制器的顶部黄色图标(ViewController图标),按住Control键拖到目标视图控制器,创建一个新的Segue,然后在右侧属性面板里给这个Segue设置唯一的Identifier,比如
LoginToHome。 - 第三步:给登录按钮添加一个IBAction(如果还没加的话),在这个方法里完成加载器显示、网络请求,最后根据结果决定是否跳转:
@IBAction func loginButtonTapped(_ sender: UIButton) { // 1. 显示加载器 let activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator.center = view.center activityIndicator.startAnimating() view.addSubview(activityIndicator) // 2. 执行登录网络请求(替换成你实际的网络代码) yourLoginNetworkRequest { [weak self] isSuccess in DispatchQueue.main.async { // 先移除加载器 activityIndicator.removeFromSuperview() if isSuccess { // 3. 登录成功,手动触发Segue self?.performSegue(withIdentifier: "LoginToHome", sender: self) } else { // 4. 登录失败,弹出提示框 let alert = UIAlertController(title: "登录失败", message: "无法登录,请检查账号密码或网络", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) } } } }
解决方案二:用
shouldPerformSegue拦截(适合不想改原有Segue的情况) 如果你不想删掉原来的Segue,也可以用这个方法拦截跳转,但逻辑稍绕一点:
- 第一步:给你的视图控制器加一个布尔属性,用来标记登录是否成功:
private var isLoginSuccess = false - 第二步:在登录按钮的IBAction里,先启动网络请求,请求完成后更新标记:
@IBAction func loginButtonTapped(_ sender: UIButton) { let activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator.center = view.center activityIndicator.startAnimating() view.addSubview(activityIndicator) yourLoginNetworkRequest { [weak self] success in DispatchQueue.main.async { activityIndicator.removeFromSuperview() self?.isLoginSuccess = success if success { // 登录成功,手动触发原来的Segue self?.performSegue(withIdentifier: "你的原有SegueIdentifier", sender: self) } else { let alert = UIAlertController(title: "错误", message: "无法登录", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) } } } } - 第三步:重写
shouldPerformSegue方法,拦截默认的Segue触发:override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { // 只拦截你的登录Segue,其他Segue正常执行 if identifier == "你的原有SegueIdentifier" { return isLoginSuccess } return true }
关键注意点
- 网络请求是异步的,所有UI操作(移除加载器、弹提示、触发Segue)必须回到主线程,所以要用
DispatchQueue.main.async包裹。 - 用
[weak self]避免循环引用,防止内存泄漏。 - 记得给Segue设置正确的Identifier,否则
performSegue会找不到Segue导致崩溃。
内容的提问来源于stack exchange,提问作者kaddie
相关产品推荐
相关产品推荐

