Oleg
Oleg

Reputation: 61

Delegate change from child view to main view

I have UIViewController with mainView and ChildView. I want change label in mainView from ChildView

enter image description here

Child I add by

let to = ChildView()
self.addChild(to)
self.mainView.addSubview(to.view)
self.mainViewConstraint.constant = to.view.frame.height
to.view.frame = self.mainView.bounds
to.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

mainView - its view, where display childView

I'm try to do this with delegate In ChildView:

protocol UserDelegate {
    func changeName(name: String)
}

class ChildView: UIViewController {

     var userDelegate: UserDelegate?

    @IBAction func changeNameBtn(_ sender: UIButton) {
        self.userDelegate?.changeName(name: "TestChanges")
    }
}

In MainView:

class MainView: UIViewController, UserDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        let ChildView = ChildView()
        ChildView.userDelegate = self
    }

    func changeName(name: String) {
        self.helloLabel.text = "Hello \(name)!"
    }
}

Upvotes: 0

Views: 341

Answers (1)

Milan Nosáľ
Milan Nosáľ

Reputation: 19747

The problem is that you present one instance of the ChildView and set a delegate on another instance of ChildView. So the child view that is presented on the screen is NOT the same one that calls the delegate. Set the delegate when you add the ChildView:

let to = ChildView()
self.addChild(to)
self.mainView.addSubview(to.view)
self.mainViewConstraint.constant = to.view.frame.height

// set the delegate here
to.userDelegate = self.mainView

to.view.frame = self.mainView.bounds
to.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

Moreover, to prevent retain cycles, use weak reference to the delegate:

protocol UserDelegate: AnyObject {
    func changeName(name: String)
}

class ChildView: UIViewController {

    weak var userDelegate: UserDelegate?

    @IBAction func changeNameBtn(_ sender: UIButton) {
        self.userDelegate?.changeName(name: "TestChanges")
    }
}

Finally, you can remove the viewDidLoad implementation from the main view:

class MainView: UIViewController, UserDelegate {
    // this should be enough
    func changeName(name: String) {
        self.helloLabel.text = "Hello \(name)!"
    }
}

Upvotes: 1

Related Questions