Samuel Mensah
Samuel Mensah

Reputation: 9

Why does this segue work but the view doesn't change?

I'm trying to use a segue to pass through some user input from a custom alert but for some reason when I perform the segue the view on the app doesn't change. But the viewdidload on the destination view controller runs, I know this because I put a print statement inside it.

More Detail

I have 3 classes here STAlert(MyCustom Alert), WorkoutLibraryViewController(The initial VC), STAddExerciseViewController(The Destination VC),

The WorkoutLib VC is connected to the Exercise VC via show segue with the "addWorkout" Identifier.

WorkoutLibraryViewController Class

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
    
    */

}

Right now my console gives me:

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

Im useing Xcode Version 15.4 on storyboard

Upvotes: 0

Views: 57

Answers (0)

Related Questions