为何Segue执行成功但界面未切换?iOS开发问题排查
自定义Alert执行Segue后界面无变化,但目标VC的viewDidLoad已执行
尝试通过Segue将自定义Alert中的用户输入传递到目标页面,执行Segue后应用界面未发生变化,但目标ViewController的viewDidLoad方法已正常运行(通过打印语句确认)。
详细信息
涉及3个类:STAlert(自定义Alert)、WorkoutLibraryViewController(初始ViewController)、STAddExerciseViewController(目标ViewController)。WorkoutLibraryViewController与STAddExerciseViewController通过Identifier为"addWorkout"的show segue在Storyboard中关联。使用Xcode 15.4版本,基于Storyboard开发。
WorkoutLibraryViewController类代码
import UIKit class WorkoutLibraryViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{ @IBOutlet weak var WorkoutList: UITableView! var workouts:[Workout] = [] let customAlert = STAlerts() @IBOutlet weak var addWorkoutButton: UIButton! override func viewDidLoad() { super.viewDidLoad() WorkoutList.delegate = self WorkoutList.dataSource = self view.backgroundColor = Colors.navyBlue // Do any additional setup after loading the view. } @IBAction func didTapCreateWorkout(_ sender: Any) { customAlert.showAlert(with: "hello world", messege: "name?", on: self) print("workoutBTN") } @objc func didTapDoneAlert(){ customAlert.didTapDoneAlert() print("Did Tap Done") } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "addWorkout"{ if let destinationVC = segue.destination as? STAddExerciseViewController { destinationVC.workoutName = customAlert.userInput print("preformed Seguea to \(destinationVC) WorkoutViewController") } else{ print("DestinationVC not set") } }else{ print("Couldn't find segue identifier") } } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ // MARK: - UITableViewDataSource Methods func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return workouts.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "WorkoutCell", for: indexPath) let workout = workouts[indexPath.row] cell.textLabel?.text = workout.name // Configure the cell as needed return cell } // MARK: - UITableViewDelegate Methods func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // Handle row selection } }
STAlert类代码
import Foundation import UIKit class STAlerts: NSObject, UITextFieldDelegate{ private var backgroundView: UIView = { let backgroundView = UIView() backgroundView.backgroundColor = .black backgroundView.alpha = 0 return backgroundView }() private let alertView: UIView = { let alert = UIView() alert.backgroundColor = Colors.greyBlue alert.layer.masksToBounds = true alert.layer.cornerRadius = 12 return alert }() private var myTargetView:UIView? var userInput: String? // user input value func showAlert(with title:String, messege:String, on viewController: UIViewController){ guard let targetView = viewController.view else { return } myTargetView = targetView backgroundView.frame = targetView.bounds targetView.addSubview(backgroundView) targetView.addSubview(alertView) alertView.frame = CGRect(x: 40, y: -300 , width: targetView.frame.size.width-80, height: 300) let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: alertView.frame.size.width, height: 80)) titleLabel.text = title titleLabel.textColor = Colors.white titleLabel.textAlignment = .center alertView.addSubview(titleLabel) let msgLabel = UILabel(frame: CGRect(x: 0, y: titleLabel.frame.minY + 10, width: alertView.frame.size.width, height: 80)) msgLabel.numberOfLines = 0 msgLabel.text = messege msgLabel.textColor = Colors.white msgLabel.textAlignment = .center alertView.addSubview(msgLabel) //<-------------------textField----------------> let textField = STTextField(frame: CGRect(x: 0, y: msgLabel.frame.maxY + 10 , width: alertView.frame.size.width-10, height: 20)) textField.delegate = self // set Delegate textField.placeholder = { let placeHolders:[String] = ["Push & Pull Split", "Arm Day", "Bodyweight Routine"] return placeHolders[Int.random(in: 0..<placeHolders.count)] }() func textFieldShouldReturn(_ textField: STTextField) -> Bool { textField.resignFirstResponder() return true } alertView.addSubview(textField) // <---------------------button-------------------> let button = UIButton(frame: CGRect(x: 0, y: alertView.frame.size.height-50, width: alertView.frame.size.width, height: 50)) alertView.addSubview(button) button.setTitle("Done", for: .normal) button.setTitleColor(Colors.energyOrange, for: .normal) button.addTarget(self, action: #selector(didTapDoneAlert), for:.touchUpInside) UIView.animate(withDuration: 0.25, animations: { self.backgroundView.alpha = 0.6 }, completion: { done in if done{ UIView.animate(withDuration: 0.25, animations: { self.alertView.center = targetView.center }) } }) } @objc func didTapDoneAlert(){ guard let targetView = myTargetView else{ print("Error: targetView is nil") return } UIView.animate(withDuration: 0.25, animations: { self.alertView.frame = CGRect(x: 40, y: -300 , width: targetView.frame.size.width-80, height: 300) }, completion:{ done in if done{ UIView.animate(withDuration: 0.25, animations: { self.backgroundView.alpha = 0 }, completion: {done in if done{ self.backgroundView.removeFromSuperview() self.alertView.removeFromSuperview() if let viewController = targetView.parentViewController() as? WorkoutLibraryViewController { print("Segue performed on view controller: \(viewController) AlertView") viewController.performSegue(withIdentifier: "addWorkout", sender: self) }else{ print("Error: Unable to find view controller to perform segue") } }}) } }) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() userInput = textField.text?.isEmpty == true ? textField.placeholder : textField.text return true } //<-------------------- Navigation ---------------> } extension UIView { func parentViewController() -> UIViewController? { var parentResponder: UIResponder? = self while let responder = parentResponder { parentResponder = responder.next if let viewController = responder as? UIViewController { return viewController } } return nil } }
STAddExerciseViewController类代码
import UIKit class STAddExerciseViewController: UIViewController, UITableViewDataSource, STExerciseTableViewCellDelegate { @IBOutlet weak var searchBar: UISearchBar! @IBOutlet weak var workoutTitle: UILabel! @IBOutlet weak var doneBtn: UIButton! @IBOutlet weak var table: UITableView! var workoutName:String? var filter:[Exercise]! var newExercises:[Exercise] = [] var exercises:[Exercise] = [Exercise(name: "Pushup", video: "pushup"), Exercise(name: "Pullup", video: "pullup"), Exercise(name: "Situp", video: "situp"), Exercise(name: "Bicep Curl", video: "bicepcurl" ), Exercise(name: "Hammer Curl", video: "hammercurl"), Exercise(name: "Barbell Curl", video: "barbellcurl"), Exercise(name: "Inclined Dumbell Curl", video: "inclinedcurl"), Exercise(name: "Spider Curl", video: "spidercurl"), Exercise(name: "Squat", video: "squat"),Exercise(name: "DeadLift", video: "deadlift"), Exercise(name: "Crunch", video: "crunch"), Exercise(name: "Russian Twist", video: "russiantwist")] override func viewDidLoad() { super.viewDidLoad() print("Adding workout") self.view.backgroundColor = Colors.navyBlue filter = exercises workoutTitle.text = workoutName table.register(STExerciseTableViewCell.nib(), forCellReuseIdentifier: STExerciseTableViewCell.identifier) table.dataSource = self while newExercises.count == 0{ doneBtn.titleLabel?.text = "Cancel" } // Do any additional setup after loading the view. } func didTapButton(with exercise: Exercise) { print(exercise.name) for i in 0..<newExercises.count{ if newExercises[i].name == exercise.name{ newExercises.remove(at: i) } else{ newExercises.append(exercise) } } doneBtn.titleLabel?.text = "Add \(newExercises.count) Exercises" } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return exercises.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: STExerciseTableViewCell.identifier, for: indexPath) as! STExerciseTableViewCell cell.configure(with: exercises[indexPath.row]) cell.delegate = self return cell } @IBAction func didTapDone(_ sender: Any) { func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation */ }
当前控制台输出
Segue performed on view controller: <StrengthTree_JSM_.WorkoutLibraryViewController: 0x10d9076a0> AlertView preformed Seguea to <StrengthTree_JSM_.STAddExerciseViewController: 0x10db3c9e0> WorkoutViewController nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint Adding workout nw_connection_copy_connected_local_endpoint_block_invoke [C1] Connection has no local endpoint
内容的提问来源于stack exchange,提问作者Samuel Mensah
相关产品推荐
相关产品推荐

