【问题标题】:How to observe notifications from a different application?如何观察来自不同应用程序的通知?
【发布时间】:2015-05-02 08:19:16
【问题描述】:

我想在某个应用程序触发事件时收到通知。我不是 Objective-C 开发人员,也不了解 OS X API——所以我希望这个问题不是太基础。

我的目标是将当前播放歌曲的元信息写入日志文件。对于 iTunes,我使用以下 Objective-C 行来实现这一点:

[[NSDistributedNotificationCenter defaultCenter]
 addObserver: myObserver selector: @selector(observeNotification:)
 name: @"com.apple.iTunes.playerInfo" object:nil];

但是,我也需要这个用于 AirServer(它是一个软件 AirPlay 接收器)。不幸的是,以下内容不起作用——观察者永远不会被调用:

[[NSDistributedNotificationCenter defaultCenter]
 addObserver: myObserver selector: @selector(observeNotification:)
 name: @"com.pratikkumar.airserver-mac" object:nil];

显然,AirServer 不会发送这些类型的通知。但是,当新歌曲开始播放时,通知中心会有通知。

我的下一步是定期检查 OS X 通知中心中的新通知(如此处所述:https://stackoverflow.com/a/25930769/1387396)。不过这并不太干净——所以我的问题是:在这种特殊情况下还有其他选择吗?

【问题讨论】:

    标签: objective-c macos cocoa foundation airserver


    【解决方案1】:

    Catalina 默默地更改了 addObserver 的行为 - 您不能再使用 nil 值作为名称来观察所有通知 - 您必须传入一个名称。这使得发现事件名称变得更加困难。

    首先,您必须了解NSDistributedNotificationCenter 中包含Notification 一词;这不相关。从About Local Notifications and Remote Notifications,它确实声明:

    注意:远程通知和本地通知与广播通知 (NSNotificationCenter) 或键值观察通知无关。

    所以,在这一点上,我将从NSDistributedNotificationCenter 的角度回答,而不是关于远程/本地通知 - 你已经在你链接的答案中找到了一个潜在的解决方案,用于观察包含一个以这种方式记录通知。

    由于 API 行为发生变化,此示例代码将无法在 Catalina (10.15) 上运行

    您需要做的第一件事是收听正确的通知。创建一个简单的应用程序来监听所有事件;例如使用:

    NSDistributedNotificationCenter *center = [NSDistributedNotificationCenter defaultCenter];
    [center addObserver:self
               selector:@selector(notificationEvent:)
                   name:nil
                 object:nil];
    
    
    -(void)notificationEvent:(NSNotification *)notif {
        NSLog(@"%@", notif);
    }
    

    表示通知为:

    __CFNotification 0x6100000464b0 {name = com.airserverapp.AudioDidStart; object = com.pratikkumar.airserver-mac; userInfo = {
        ip = "2002:d55e:dbb2:1:10e0:1bfb:4e81:b481";
        remote = YES;
    }}
    __CFNotification 0x618000042790 {name = com.airserverapp.AudioDidStop; object = com.pratikkumar.airserver-mac; userInfo = {
        ip = "2002:d55e:dbb2:1:10e0:1bfb:4e81:b481";
        remote = YES;
    }}
    

    这表示addObserver调用中的name参数应该是com.airserverapp.AudioDidStartcom.airserverapp.AudioDidStop

    您可以使用这样的代码来确定所有通知,这将允许您在需要特定观察者时添加相关观察者。这可能是观察此类通知的最简单方法。

    【讨论】:

    • 很好的答案——非常感谢。这澄清了事情!所以AirServer没有把我需要的元数据放在userInfo中。如果这是他们可以添加的内容,我想我会请求他们的支持。
    • 以上代码不起作用,或者我使用 macOS 10.15.1 (19B2106)。如果我用@"com.apple.iTunes.playerInfo" 替换name 值,通知就会起作用。
    • 是的,Catalina 的行为发生了未记录的变化。
    • 它似乎仍然可以使用 usingBlock: 参数。 stackoverflow.com/a/7955014/2693925
    • 这与NSDistributedNotificationCenter 相关,而不是NSNotificationCenter。当您在沙盒应用程序中尝试时,有一个有点有用的attempt to register for all distributed notifications thwarted by sandboxing,在非沙盒应用程序中它只是忽略它。
    猜你喜欢
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    相关资源
    最近更新 更多