Home > Enterprise >  Setting Observer for Swift Objects/Properties
Setting Observer for Swift Objects/Properties

Time:11-26

I've been looking for a way to trigger a method when the number of displays connected to a mac changes. I know I can get the value of NSScreen.screens.count, but I need to find a way to create a notification or something when that value changes or something else that would indicate a change in the number of displays connected.

I have tried KVO examples here and here, but in order for either of those to work there needs to be an event that triggers the methods inside the class.

In essence this is what I would like to do based on the first link:


class EventObserverDemo {
    var statusObserver: NSKeyValueObservation?
    var objectToObserve: NSScreen.screens.count?
    
    func registerAddObserver() -> Void {
        statusObserver = objectToObserve?.observe(NSScreen.screens.count, options: [.new, .old], changeHandler: {[weak self] (NSScreen.screens.count, change) in
            if let value = change.newValue {
                // observed changed value and do the task here on change.
                print("The display count has changed.")
            }
        })
    }
    
    func unregisterObserver() -> Void {
        if let sObserver = statusObserver {
            sObserver.invalidate()
            statusObserver = nil
        }
    }
}

I tried using a notification that used NSScreen.colorSpaceDidChangeNotification but that does not trigger a notification if a display is disconnected.

I would like to find a way to detect any time an external display is connected or disconnected. There has to be something I haven't found yet because whenever I plug in an external display to my mac I see the screen on the main display change, so there's some kind of notification that something changed whether I plug in a display or unplug it from my mac.

I looked at the didSet function, but I couldn't figure out a way to implement that on NSScreen.screens.count property.

I also looked into a property wrapper for NSScreen.screens.count but again I couldn't figure that out either.

CodePudding user response:

You can observe the NSApplication.didChangeScreenParametersNotification notification. This example will only print once each time a display is either connected or disconnected, and what the change was in the number of screens.

Code:

class EventObserverDemo {
    var lastCount = NSScreen.screens.count

    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(trigger),
            name: NSApplication.didChangeScreenParametersNotification,
            object: nil
        )
    }

    @objc private func trigger(notification: NSNotification) {
        let newCount = NSScreen.screens.count

        if newCount != lastCount {
            print("Switched from \(lastCount) to \(newCount) displays")
            lastCount = newCount
        }
    }
}

You don't need to remove/invalidate the observer either, easier to let the system handle it:

If your app targets iOS 9.0 and later or macOS 10.11 and later, you do not need to unregister an observer that you created with this function. If you forget or are unable to remove an observer, the system cleans up the next time it would have posted to it.

  • Related