swiftnjava
swiftnjava

Reputation: 26

What error am I making when trying to pass data between ViewControllers using closures?

My main View Controller has an embedded UITabbarController in it. There are 2 subVCs: viewControllerONE & viewControllerTWO.

viewControllerONE displays a label showing the user's current score, and viewControllerTWO displays a button, pressing which should display an error window on viewControllerONE. (For the sake of simplicity, the user has to manually navigate to viewControllerONE using the tab bar to see the error, ie, pressing the button on viewControllerTWO doesn't take you to viewControllerONE and then display the errorWindow.)

The error window is a simple UIView class.

From SO, I have learnt that the best way to pass data in swift isn't delegates but closures, as the former is more of an objective C design, and so I've used closures to pass data between view controllers.

So here is my viewControllerONE code:

class ViewControllerONE: UIViewController {

    var score = 10

    lazy var scoreLabel: UILabel = {
        let label = UILabel()
        label.text = String(score)
        label.font = .systemFont(ofSize: 80)
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textAlignment = .center
        return label
    }()


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        view.addSubview(scoreLabel)

         let VC = ViewControllerTWO()

    VC.callback = { [weak self ] in
        let error = errorView()
        self?.view.addSubview(error)
        }


        NSLayoutConstraint.activate([
        scoreLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        scoreLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    ])

  }

}

and here is my viewControllerTWO code:

class ViewControllerTWO: UIViewController {

    var callback: (() -> Void)?

    let buttonTwo: UIButton = {
             let button = UIButton()
             button.setTitle("HIT THIS BUTTON!", for: .normal)
             button.backgroundColor = .systemBlue
             button.translatesAutoresizingMaskIntoConstraints = false
             button.addTarget(self, action: #selector(buttonTwoPressed), for: .touchUpInside)
             button.layer.cornerRadius = 8
             return button
         }()

         @objc func buttonTwoPressed() {
             print("PRESSEDDDD")
            callback?()
         }


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        view.addSubview(buttonTwo)

                 NSLayoutConstraint.activate([
                 buttonTwo.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                 buttonTwo.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
    }

}

And here is the error view:

class ErrorView: UIView {


    fileprivate let dismissButton: UIButton = {
        let button = UIButton()
        button.setTitle("DISMISS!!!!", for: .normal)
        button.backgroundColor = .systemBlue
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(dismissButtonPressed), for: .touchUpInside)
        button.layer.cornerRadius = 12
        return button
    }()

    @objc func dismissButtonPressed() {
    self.errorGoAway()
    }


    fileprivate let errorViewBox: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .white
        v.layer.cornerRadius = 24
        return v
    }()

    @objc fileprivate func errorGoAway() {
            self.alpha = 0
    }

    @objc fileprivate func errorShow() {
        self.alpha = 1
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(errorGoAway)))
        self.backgroundColor = UIColor.gray
        self.backgroundColor?.withAlphaComponent(0.8)
        self.frame = UIScreen.main.bounds
        self.addSubview(errorViewBox)

        errorViewBox.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        errorViewBox.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        errorViewBox.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.7).isActive = true
        errorViewBox.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.45).isActive = true

        errorViewBox.addSubview(dismissButton)
        dismissButton.leadingAnchor.constraint(equalTo: errorViewBox.leadingAnchor).isActive = true
        dismissButton.trailingAnchor.constraint(equalTo: errorViewBox.trailingAnchor).isActive = true
        dismissButton.centerYAnchor.constraint(equalTo: errorViewBox.centerYAnchor).isActive = true
        dismissButton.heightAnchor.constraint(equalTo: errorViewBox.heightAnchor, multiplier: 0.15).isActive = true

        errorShow()
    }

Upvotes: 0

Views: 84

Answers (1)

isHidden
isHidden

Reputation: 860

You need to get your controller from tabBarController instead of create new instance:

class ViewControllerONE: UIViewController {

var score = 10

lazy var scoreLabel: UILabel = {
    let label = UILabel()
    label.text = String(score)
    label.font = .systemFont(ofSize: 80)
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textAlignment = .center
    label.textColor = .blue
    return label
}()


override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .white

    view.addSubview(scoreLabel)

    var VC: ViewControllerTWO?

    let arrayOfVC = self.tabBarController?.viewControllers ?? []

    for item in arrayOfVC {
        if let secondVC = item as? ViewControllerTWO {
            VC = secondVC
            break
        }
    }

    VC?.callback = { [weak self ] in
        let error = ErrorView()
        self?.view.addSubview(error)
    }

    NSLayoutConstraint.activate([
        scoreLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        scoreLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    ])

  }
}

Upvotes: 1

Related Questions