Objective c CGDisplayRegisterReconfigurationCallback:未调用回调

Objective c CGDisplayRegisterReconfigurationCallback:未调用回调,objective-c,screen,Objective C,Screen,为什么函数displayChanged在下面的代码中没有被激发 #import <Cocoa/Cocoa.h> static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) { NSLog(@"%@, %@", displayID, flags); } int main(int argc, const char * ar

为什么函数displayChanged在下面的代码中没有被激发

#import <Cocoa/Cocoa.h>

static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) {
    NSLog(@"%@, %@", displayID, flags); 
}

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);

        CFRunLoopRun();
    }
    return 0;
}
我正在物理上卸下并插入外部显示器,但该功能从未运行过。 为什么?

我无法让CGDisplayRegisterReconfigurationCallback工作,所以我改用分布式通知:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"com.apple.BezelServices.BMDisplayHWReconfiguredEvent" object:nil queue:nil usingBlock:^(NSNotification *notification) {
            NSLog(@"Displays changed!");
        }];

        CFRunLoopRun();
    }
    return 0;
}
我无法使CGDisplayRegisterReconfigurationCallback正常工作,因此我改为使用分布式通知:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [[NSDistributedNotificationCenter defaultCenter] addObserverForName:@"com.apple.BezelServices.BMDisplayHWReconfiguredEvent" object:nil queue:nil usingBlock:^(NSNotification *notification) {
            NSLog(@"Displays changed!");
        }];

        CFRunLoopRun();
    }
    return 0;
}

如果您正在使用AppKit并且有一个正在运行的NSApplication事件循环,则可以侦听NSApplicationIDChangeScreen参数通知。或者,您可以在应用程序委托中实现-applicationIDChangeScreenParameters:方法,这与此相同。

如果您正在使用AppKit并且有一个正在运行的NSApplication事件循环,则可以侦听NSApplicationIDChangeScreenParameters通知。或者,您可以在应用程序委托中实现-applicationIDChangeScreenParameters:方法,这相当于一件事。

刚刚在上找到了解决方案

在调用CFRunLoopRun之前,必须调用NSApplicationLoad以建立与窗口服务器的连接。这是原始问题的固定代码:

#import <Cocoa/Cocoa.h>

static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) {
    NSLog(@"%u, %u", displayID, flags); 
}

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);

        NSApplicationLoad();  // establish a connection to the window server. In <Cocoa/Cocoa.h>
        CFRunLoopRun();       // run the event loop
    }
    return 0;
}

刚找到解决方案

在调用CFRunLoopRun之前,必须调用NSApplicationLoad以建立与窗口服务器的连接。这是原始问题的固定代码:

#import <Cocoa/Cocoa.h>

static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) {
    NSLog(@"%u, %u", displayID, flags); 
}

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);

        NSApplicationLoad();  // establish a connection to the window server. In <Cocoa/Cocoa.h>
        CFRunLoopRun();       // run the event loop
    }
    return 0;
}

您在那里所做的并不是真正的Objective C。请尝试实例化一个Objective C对象,并将您的CGDisplayRegisterReconfigurationCallback函数调用放入其中。我之所以建议这样做,是因为我认为您的代码直接进入CFRunLoopRun,任何不在目标C对象上下文中的回调都不会有机会被调用。@MichaelDautermann我想我不明白,但是你能提供一些代码来做这件事吗?你在那里做的不是真正的Objective C。试着实例化一个Objective C对象,并将你的CGDisplayRegisterReconfigurationCallback函数调用放在其中。我建议这样做的原因是,我认为您的代码直接进入CFRunLoopRun,任何不在目标C对象上下文中的回调都没有被调用的机会。@MichaelDautermann我想我不明白,但您能提供一些这样做的代码吗?这是为守护进程编写的,所以我没有任何用户界面。好的。我不确定,因为您导入了,其中包括AppKit。它是用于守护程序的,所以我没有任何用户界面。好的。我不确定,因为您导入了,其中包括AppKit。这是一个更好的解决方案,也适用于OS X 10.10,与我的答案不同。这是一个更好的解决方案,也适用于OS X 10.10,与我的答案不同。您从何处获得有关通知名称的信息?com.apple.BezelServices.BMDisplayHWReconfiguredEvent有相关文档吗?@MalachiHolden我不知道。您从哪里获得通知使用的名称的信息?com.apple.BezelServices.bmdisplayhwedevent有相关文档吗?@MalachiHolden我不知道。