0

How to detect when a new display is connected or disconnected on macOS (Swift or Objective-C).

I tried something like this but it doesn't seem to work:

NSDistributedNotificationCenter *nc = [NSDistributedNotificationCenter defaultCenter];
[nc addObserverForName:NSApplicationDidChangeScreenParametersNotification
                   object:[NSApplication sharedApplication]
                    queue:[NSOperationQueue mainQueue]
               usingBlock:^(NSNotification *notification) {
                  NSLog(@"Notification %@", notification);
               }];
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 1
    You don't want to use `NSDistributedNotificationCenter`. You just want `NSNotificationCenter'. Also, you should keep a strong reference to the observer token object returned. – Ken Thomases May 08 '19 at 16:19
  • 1
    Possible duplicate of [How can you detect the connection and disconnection of external monitors on the Mac?](https://stackoverflow.com/questions/14507312/how-can-you-detect-the-connection-and-disconnection-of-external-monitors-on-the) – TheNextman May 08 '19 at 17:17
  • Thanks, using NSNotificationCenter solved the problem. First I tried the solution with CGDisplayRegisterReconfigurationCallback suggested by TheNextman but it didn't work. I actually liked this solution better and a strange observation was that when I added the solution with addObserverForName, the solution with CGDisplayRegisterReconfigurationCallback began to work!? Removing addObserverForName again and CGDisplayRegisterReconfigurationCallback stopped to work. PS: This code is used in a Daemon if that makes any difference. – Ole Bjørn Setnes May 09 '19 at 22:05

1 Answers1

2

Swift 5.5.1

You can use the notification NSApplication.didChangeScreenParametersNotification

import Cocoa

class ViewController: NSViewController {

    var externalDisplayCount:Int = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        externalDisplayCount = NSScreen.screens.count
        setupNotificationCenter()
    }

    func setupNotificationCenter() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleDisplayConnection),
            name: NSApplication.didChangeScreenParametersNotification,
            object: nil)
    }

    @objc func handleDisplayConnection(notification: Notification) {
        if externalDisplayCount < NSScreen.screens.count {
            print("An external display was connected.")
            externalDisplayCount = NSScreen.screens.count
        } else if externalDisplayCount > NSScreen.screens.count {
            print("An external display was disconnected.")
            externalDisplayCount = NSScreen.screens.count
        } else {
            print("A display configuration change occurred.")
        }
    }
}

Notice that the final else is there and will be triggered whenever something changes with any of the connected displays configuration, such as toggling fullscreen mode on a display, or through system preferences.

You can see question here.

SouthernYankee65
  • 1,129
  • 10
  • 22