iOS天气App中Segue无法按条件正常工作问题求助
iOS Weather App Segue 触发与数据传递问题排查与修复
你遇到的Segue无法正常触发和传递数据的问题,我帮你排查了代码里的几个关键问题,下面逐一分析并给出修复方案:
问题1:prepare(for:sender:) 方法未正确重写
你写的prepare方法签名有误,导致系统根本不会调用这个方法,自然无法传递数据:
// 错误写法 func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
正确的写法需要加上override关键字,并且sender的类型是Any?而不是AnyObject?:
// 正确写法 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
问题2:主动调用performSegue与shouldPerformSegue的逻辑冲突
当你主动调用performSegue(withIdentifier:sender:)时,系统会先触发shouldPerformSegue的判断。虽然你在回调里设置了userInputLocationSuccess = true,但有两个细节需要调整:
- 在
goButtonTapped的异步回调中,你先弹出了Alert再调用performSegue,但Alert弹出后会阻断UI交互,Segue的触发会被延迟。建议去掉Alert后直接执行Segue,或者在Alert的确认回调里触发Segue。 - 确保
shouldPerformSegue里的状态判断逻辑和主动触发时的状态一致,比如userInputLocationSuccess在验证通过后确实被设为true(这部分你已经用DispatchQueue.main.async处理了线程问题,是正确的)。
问题3:Core Location 逻辑中的冗余操作
在getMyLocationWeatherTapped里你初始化了locationManager并调用requestLocation(),但在didChangeAuthorization里又调用startUpdatingLocation(),这会导致位置更新被重复触发。建议调整逻辑:
@IBAction func getMyLocationWeatherTapped(_ sender: UIButton) { self.locationManager = CLLocationManager() self.locationManager?.delegate = self self.locationManager?.desiredAccuracy = kCLLocationAccuracyHundredMeters let status = CLLocationManager.authorizationStatus() if status == .authorizedWhenInUse { self.locationManager?.requestLocation() } else { self.locationManager?.requestWhenInUseAuthorization() } } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { if status == .authorizedWhenInUse { self.locationManager?.requestLocation() // 用requestLocation替代startUpdatingLocation,只获取一次位置 } else if status == .denied || status == .restricted { presentAlert("Location Access Denied", message: "Please enable location access in settings", cancelTitle: "OK") } }
问题4:错误处理中的Segue调用错误
在locationManager(_:didFailWithError:)里,你错误调用了shouldPerformSegue(这只是判断方法,不是触发方法),而且Segue标识符也写错了(应该是coreLocationButtonSegue而不是coreLocationButton),这里应该直接提示用户,不需要触发Segue:
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { SVProgressHUD.dismiss() presentAlert("Location Not Found", message: "Provide zipcode, address or city", cancelTitle: "OK") self.coreLocationSuccess = false // 重置状态 }
修改后的完整关键代码示例
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { print("ENTERED INTO THE SEGUE FUNCTION") if segue.identifier == "goButtonSegue"{ if let destinationVC = segue.destination as? WeatherForecastViewController { guard let neededZipcode = self.zipCodeTextField.text else {print("neededZipcode did not unwrap"); return} destinationVC.zipCode = neededZipcode } } else if segue.identifier == "coreLocationButtonSegue"{ if let destinationVC = segue.destination as? WeatherForecastViewController { guard let userLocation = currentLocation else {print("did not pass user location"); return} destinationVC.coordinateHolder = userLocation // 这里用userLocation更清晰 } } } @IBAction func goButtonTapped(_ sender: Any) { SVProgressHUD.show(withStatus: "Finding Your Location") guard let userText = self.zipCodeTextField.text, !userText.isEmpty else { SVProgressHUD.dismiss() presentAlert("Invalid Input", message: "Please enter a zipcode", cancelTitle: "OK") return } GoogleCoordinateAPIClient.isAddressValid(zipCode: userText) { (boolValue) in DispatchQueue.main.async { SVProgressHUD.dismiss() if boolValue { self.userInputLocationSuccess = true // 直接触发Segue,或者在Alert的确认回调里执行 self.performSegue(withIdentifier: "goButtonSegue", sender: self) } else { self.userInputLocationSuccess = false self.presentAlert("Invalid Input", message: "Please re-enter valid input", cancelTitle: "OK") } } } }
按照这些修改后,Segue应该能正常触发并传递数据了。
内容的提问来源于stack exchange,提问作者Sara
相关产品推荐
相关产品推荐

