NSView unable to observe NSWindow changes - KVO and Swift

583 views Asked by At

I'm having a hard time getting my NSView to observe changes in its parent NSWindow. I tried this on a test project with nothing more than an NSWindow which contains a MyView subclass of NSView just to see if I'm missing something.

class MyView: NSView {

    //add observer on awake from nib
    //works fine
    override func awakeFromNib() {
        if let win = self.window {
            win.addObserver(self, forKeyPath: Notification.Name.NSWindowDidBecomeKey.rawValue, options: .new, context: nil)
        }
    }

    //remove observer on dealloc
    //allso works fine
    deinit {
        if let win = self.window {
            win.removeObserver(self, forKeyPath: Notification.Name.NSWindowDidBecomeKey.rawValue)
        }
    }

    //never gets called
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        Swift.print(keyPath ?? "")
        Swift.print("worked!")
    }

    override func draw(_ dirtyRect: NSRect) {
        NSColor.blue.set()
        NSBezierPath.fill(dirtyRect)
    }
} 

I have also tried the suggestions here but no luck. I've also checked other answers and couldn't find an answer. Most cover making your own class KVO compliant. I want to observe an NSWindow object. What am I missing?

1

There are 1 answers

0
MAH On BEST ANSWER

So it looks like NSWindowDidBecomeKey is a Notification needs to be posted to the default NotificationCenter rather than the window itself. This is the correct code that works

class MyView: NSView {

    //add observer on awake from nib
    //works fine
    override func awakeFromNib() {
        if let win = self.window {
            NotificationCenter.default.addObserver(self, selector: #selector(self.windowIsKey(_:)), name: .NSWindowDidBecomeKey, object: win)
        }
    }

    //remove observer on dealloc
    //allso works fine
    deinit {
        if let win = self.window {
            NotificationCenter.default.removeObserver(self, name: .NSWindowDidBecomeKey, object: win)
        }
    }

    //now this method is called and works fine
    func windowIsKey(_ notification: Notification) {
        Swift.print("worked!")
    }
}