action method doesn't work in view controller

Hi, I'm using Xcode 10 and macOS 10.14, I have a problem with IBAction method...

I created OtherViewController.swift/OtherViewController.xib, created a IBAction method (closeView:) which simply calls removeFromSuperview, and connected action (button) to file's owner (OtherViewController).

class OtherViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
    }
    
    @IBAction func closeView(_ sender: NSButton) {
        print("closeView()")
        self.view.removeFromSuperview()
    }
}


When i run the app, hit the button, the action is not called.

I just called a method like below when I hit main window button...

    @IBAction func showOtherView(_ sender: NSButton) {
        let otherView : OtherViewController! = OtherViewController()
        otherView.view.frame = tabView.frame
        tabView.isHidden = true
        window.contentView?.addSubview(otherView.view)
    }


I can't figure it out what is the problem. I thought it should be work in older version of xcode...

Accepted Reply

That's not you create a view controller that has a NIB for its view. You must use the "init(nibName:bundle:)" initializer so that the new view controller knows where to find its view NIB.


You almost certainly want to keep a reference to the OtherViewController you create in "showOtherView" as an instance property, not just a local variable. Otherwise, when the function returns, the OtherViewController will be deallocated — there's nothing keeping it alive, since views don't have references to their view controllers. The view will remain, but behavior in the view controller will disappear, and (since part of the job of a view controller is to keep all of the top-level objects of is NIB alive) there may be other UI objects that will disappear along with it.


Alternatively, you could use "addChild" to make your OtherViewController a child of the main view controller. That will keep it alive, and avoid the need for an instance property.

Replies

That's not you create a view controller that has a NIB for its view. You must use the "init(nibName:bundle:)" initializer so that the new view controller knows where to find its view NIB.


You almost certainly want to keep a reference to the OtherViewController you create in "showOtherView" as an instance property, not just a local variable. Otherwise, when the function returns, the OtherViewController will be deallocated — there's nothing keeping it alive, since views don't have references to their view controllers. The view will remain, but behavior in the view controller will disappear, and (since part of the job of a view controller is to keep all of the top-level objects of is NIB alive) there may be other UI objects that will disappear along with it.


Alternatively, you could use "addChild" to make your OtherViewController a child of the main view controller. That will keep it alive, and avoid the need for an instance property.

You're right! I added a reference to the view controller and it works. Thanks for your reply!