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是同一条事件链路。
