OS X应用开发:如何获取通过Custom URL Scheme唤起当前应用的源应用信息?
获取macOS应用中唤起当前应用的源应用信息
你提到的通过PID匹配的方案确实能解决问题,但确实有更优雅的方式——直接从触发的Apple Event中提取源应用的Bundle ID,不用遍历所有运行中的应用。
在macOS的Apple Event机制里,唤起你的应用的事件本身就携带了源应用的Bundle ID属性,对应的AE关键字是keySenderBundleIDAttr(定义在AEKeyword中)。你可以直接从事件对象中读取这个属性,一步到位获取Bundle ID,再通过Bundle ID快速定位到应用信息。
修改后的代码示例
class AppDelegate: NSObject, NSApplicationDelegate { func applicationWillFinishLaunching(_ notification: Notification) { NSAppleEventManager .shared() .setEventHandler( self, andSelector: #selector(handleURL(event:reply:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL) ) NSLog("Debug: Handle Set") } @objc func handleURL(event: NSAppleEventDescriptor, reply: NSAppleEventDescriptor) { // 1. 获取传入的URL if let path = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue?.removingPercentEncoding { NSLog("Opened URL: \(path)") } // 2. 直接从Apple Event中获取源应用的Bundle ID if let bundleIDDescriptor = event.attributeDescriptor(forKeyword: AEKeyword(keySenderBundleIDAttr)), let sourceBundleID = bundleIDDescriptor.stringValue { NSLog("Source App Bundle ID: \(sourceBundleID)") // 3. (可选)通过Bundle ID获取源应用的本地化名称 if let sourceApp = NSWorkspace.shared.runningApplications.first(where: { $0.bundleIdentifier == sourceBundleID }) { if let appName = sourceApp.localizedName { NSLog("Source App Name: \(appName)") } } } } }
为什么这个方案更优?
- 更直接:不需要先获取PID再遍历所有运行应用,直接从事件中读取Bundle ID,减少了中间步骤
- 性能更好:避免了遍历
runningApplications的开销,尤其是当系统运行大量应用时 - 更可靠:直接依赖系统传递的属性,比PID匹配的方式更稳定(PID可能会被复用,但Bundle ID是应用的唯一标识)
如果只需要Bundle ID,那么步骤2就足够了;如果需要应用名称,通过Bundle ID查找的方式也比遍历所有应用高效得多——因为runningApplications.first(where:)会在找到匹配项后立即停止遍历。
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

