macOS接收和分发事件的NSAppleEventManager
macOS接收和分发事件的NSAppleEventManager

macOS接收和分发事件的NSAppleEventManager

NSAppleEventManager 是 macOS 中用于接收和分发 Apple Events(苹果事件)的核心系统类,专门负责应用之间、系统与应用之间的高层通信。

Apple Events是什么?

Apple Events 是 macOS 从 Classic Mac OS 时代沿用至今的一套 IPC(进程间通信)机制。

当系统通知 App 打开文件、打开 URL 或者通过 URL Scheme(深层链接)打开应用时,NSAppleEventManager负责将事件分发给App。

基本作用

NSAppleEventManager主要用于注册事件处理函数、接收系统发送的Apple Events,并将事件分发给指定的方法。

例如:

NSAppleEventManager.shared().setEventHandler(
    self,
    andSelector: #selector(handleURLEvent(_:withReplyEvent:)),
    forEventClass: AEEventClass(kInternetEventClass),
    andEventID: AEEventID(kAEGetURL)
)

这段代码表示,当系统向 App 发送“某种 Apple Event”时,调用指定的方法来处理。

参数说明:

1、self表示事件处理对象(通常是AppDelegate)。

2、#selector(handleURLEvent(_:withReplyEvent:)) 表示收到事件后调用的方法,这里调用的是handleURLEvent方法。

3、forEventClass表示事件分类,kInternetEventClass为互联网事件。

4、andEventID表示具体时间,kAEGetURL为获取/打开URL。

在某些版本中,编译器无法自动推断UInt32为AEEventClass/AEEventID,因此需要显式类型转换为AEEventClass(…)/AEEventID(…)。

使用示例

当用户或者其他App调用“打开 URL”事件时:

ImageSlim://open-shared-images

系统会向 App 发送该事件:

NSAppleEventManager.shared().setEventHandler(
    self,
    andSelector: #selector(handleURLEvent(_:withReplyEvent:)),
    forEventClass: AEEventClass(kInternetEventClass),
    andEventID: AEEventID(kAEGetURL)
)

App 收到“打开 URL”事件时,调用handleURLEvent方法进行处理。

@objc func handleURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) {
    guard let urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue,
          let url = URL(string: urlString) else {
        print("无效的 URL 事件")
        return
    }
    
    print("收到 URL: \(url.absoluteString)")
    
    if url.scheme == "imageslim", url.host == "open-shared-images" {
        // 处理 URL 文件
        handleSharedImages()
    }
}

代码解析:

1、解析 Apple Event中的URL

event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue

event包含完整的Apple Event消息,keyDirectObject为事件的“主体参数”, stringValue表示取出字符串形式,相等于从系统事件包中取出真正的 URL 文本。

例如,可以从URL Scheme中获取字符串:

imageslim://open-shared-images

构建Swift的URL对象:

let url = URL(string: urlString)

用于后续解析scheme、host、path、query等参数。

校验路由判断:

if url.scheme == "imageslim", url.host == "open-shared-images"

根据路由判断处理的方法,并执行相关的业务逻辑。

Application方法

在macOS 10.6+引入application方法,和可打开应用的方法一致。

当打开应用时,会进入ApplicationDelegate的application(_:open:)方法,处理URL。

// 现代方法:通过 application 接收分发的 URL 事件
func application(_ application: NSApplication, open urls: [URL]) {
    print("通过 application(_:open:) 接收到 URL")
    for url in urls {
        // URL Scheme 分发的事件,例如:ImageSlim://open-shared-images
        if url.scheme == "ImageSlim", url.host == "open-shared-images" {
            handleSharedImages()
        } else {
            // 其他分发的事件
            Task {
                await FileProcessingService.shared.fileImporter(urls)
            }
        }
    }
}

// 旧方法:NSAppleEventManager,仅在需要更底层控制时使用
func applicationDidFinishLaunching(_ aNotification: Notification) {
    NSAppleEventManager.shared().setEventHandler(
        self,
        andSelector: #selector(handleURLEvent(_:withReplyEvent:)),
        forEventClass: AEEventClass(kInternetEventClass),
        andEventID: AEEventID(kAEGetURL)
    )
}

总结

NSAppleEventManager 是 macOS 负责处理/接收“系统/其他 App的高层事件分发器。

在macOS 10.6+版本中,可以使用application(_:open:)方法处理URL/文件事件,和NSAppleEventManager是同一条事件链路。

相关文章

1、SwiftUI配置深层链接

2、macOS Event Class事件

3、macOS应用配置文件的可打开应用

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注