Search code examples
iosswiftmodel-view-controlleruiviewuiviewcontroller

Can't make changes in View from Controller


I'm trying to create my first MVC project, which will check code phrase and open access to user. I've created 3 files:

  1. Model - checks if the code phrase is correct and returns a result that is used as the UILabel text.
import Foundation

class passwordCheck {
    public static let model = passwordCheck()
    
    func passwordChecking (_ word: String) -> String {
        if word == "leohl" {
            return "Hello"
        } else {
            return "Error"
        }
    }
}
  1. View - responsible for displaying the UI to the user. Contains UILabel for status and UIButton to start identification process.
import UIKit

class View: UIView {
    
    public let helloLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.textColor = .black
        label.text = "Password?"
        label.font = .systemFont(ofSize: 20, weight: .bold)
        label.frame = CGRect(x: UIScreen.main.bounds.width/2-75, y: UIScreen.main.bounds.height/2-300, width: 150, height: 30)
        return label
    }()
    
    public let startButton: UIButton = {
        let button = UIButton()
        button.setTitle("Start", for: .normal)
        button.backgroundColor = .red
        button.frame = CGRect(x: UIScreen.main.bounds.width/2-50, y: UIScreen.main.bounds.height/2-50, width: 100, height: 50)
        button.layer.cornerRadius = 5
        button.setTitleColor(.orange, for: .highlighted)
        return button
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        addSubview(helloLabel)
        addSubview(startButton)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
    }
}
  1. ViewController - call UIAlertController when UIButton is pressed. This changes the background colour of the view and the UILabel text.
import UIKit

class ViewController: UIViewController {
    let myView = View()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let safeArea = view.safeAreaLayoutGuide.layoutFrame
        let theView = View(frame: safeArea)
        theView.startButton.addTarget(self, action: #selector(alertCheck), for: .touchUpInside)
        view.addSubview(theView)
    }
    
    @objc func alertCheck() {
        callAlert(alertTitle: "Identify yourself", alertMessage: "Type the code phrase")
    }
    
    func callAlert(alertTitle: String, alertMessage: String) {
        let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { action in
            self.myView.helloLabel.text = passwordCheck.model.passwordChecking(alert.textFields?.first?.text ?? "")
        }))
        alert.addTextField()
        self.present(alert, animated: true)
        print("Button working")
    }
}

So the problem is: everything seems to work, but when I enter the code phrase in the alert, nothing changes. Terminal says me:

-[RTIInputSystemClient remoteTextInputSessionWithID:performInputOperation:] perform input operation requires a valid sessionID


Solution

  • I think the main problem is in my model itself, so I've changed it: combined View and ViewController files so I have only two: ViewController and Model.

    ViewController:

    import UIKit
    
    class ViewController: UIViewController {
        let myView = View()
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
        }
        
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            let safeArea = view.safeAreaLayoutGuide.layoutFrame
            let theView = View(frame: safeArea)
            theView.startButton.addTarget(self, action: #selector(alertCheck), for: .touchUpInside)
            view.addSubview(theView)
        }
        
        @objc func alertCheck() {
            callAlert(alertTitle: "Identify yourself", alertMessage: "Type the code phrase")
        }
        
        func callAlert(alertTitle: String, alertMessage: String) {
            let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
            alert.addTextField()
            alert.addAction(UIAlertAction(title: "Done", style: .default, handler: { action in
                self.myView.helloLabel.text = passwordCheck.model.passwordChecking(alert.textFields?.first?.text ?? "")
            }))
            self.present(alert, animated: true)
            print("Button working")
        }
    }
    

    Model:

    import Foundation
    
    class Model {
        public static let model = Model()
        
        func passCheck (_ word: String) -> String {
            if word == "leohl" {
                return "Hello"
            } else {
                return "Error"
            }
        }
    }
    

    Now everything works as it should. But if you have any additions, I would love to hear them!