点击AppKit showDefinition生成的释义视图时macOS应用崩溃求助
macOS应用调用AppKit的showDefinition(for:at)生成释义视图后,点击该视图会崩溃,崩溃日志错误信息:
Fault: deferNSXPCInvocationOntoMainThread_block_invoke caught NSInternalInconsistencyException '_CPSSetFrontProcessWithOptions failed due to CGError -606 4294966690 fffffda2 (appIsDaemon)'
已尝试的解决措施:
- 用
DispatchQueue.main.async包裹相关代码 - 将DefinitionWindow设为全局变量手动控制生命周期
但问题仍未解决。
开发环境:macOS 14.3.1、Xcode 15
可复现的完整代码(需在隐私设置中开启辅助功能权限):
import Cocoa import SwiftUI import AppKit class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { NSEvent.addGlobalMonitorForEvents(matching: .keyDown) { [weak self] event in guard let self = self else { return } if event.modifierFlags.contains(.command) && event.charactersIgnoringModifiers == "c" { self.ShowWordDefinition() } } NSApp.servicesProvider = self NSApp.registerServicesMenuSendTypes([.string], returnTypes: []) } func ShowWordDefinition(){ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { let attributedString = NSAttributedString(string:NSPasteboard.general.string(forType: .string)!) let DefinitionWindow = NSWindow(contentRect: NSRect(origin: .zero, size: NSSize(width: 1, height: 1)), styleMask: [.borderless], backing: .buffered, defer: false) // on the top DefinitionWindow.level = .floating let pointInWindow = NSPoint(x:0,y:0); //default value DefinitionWindow.contentView?.showDefinition(for: attributedString, at: pointInWindow) DefinitionWindow.orderFront(nil) } } } let delegate = AppDelegate() let app = NSApplication.shared app.delegate = delegate app.run()
完整崩溃日志:
FAULT: deferNSXPCInvocationOntoMainThread_block_invoke caught NSInternalInconsistencyException '_CPSSetFrontProcessWithOptions failed due to CGError -606 4294966690 fffffda2 (appIsDaemon)' with backtrace (
"0 CoreFoundation __exceptionPreprocess + 176",
"1 libobjc.A.dylib objc_exception_throw + 60",
"2 CoreFoundation +[NSException exceptionWithName:reason:userInfo:] + 0",
"3 ViewBridge assertCGError + 80",
"4 ViewBridge -[NSRemoteView serviceWindowWouldActivate] + 724",
"5 CoreFoundation invoking + 148",
"6 CoreFoundation -[NSInvocation invoke] + 428",
"7 ViewBridge __deferNSXPCInvocationOntoMainThread_block_invoke + 120",
"8 ViewBridge __wrapBlockWithVoucher_block_invoke + 56",
"9 ViewBridge deferredBlockOpportunity_block_invoke_2 + 360",
"10 CoreFoundation CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK + 28",
"11 CoreFoundation __CFRunLoopDoBlocks + 356",
"12 CoreFoundation __CFRunLoopRun + 2440",
"13 CoreFoundation CFRunLoopRunSpecific + 608",
"14 HIToolbox RunCurrentEventLoopInMode + 292",
"15 HIToolbox ReceiveNextEventCommon + 648",
"16 HIToolbox _BlockUntilNextEventMatchingListInModeWithFilter + 76",
"17 AppKit _DPSNextEvent + 660",
"18 AppKit -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 716",
"19 AppKit -[NSApplication run] + 476",
"20 try main + 160",
"21 dyld start + 2360"
)
崩溃根源是系统将你的应用识别为守护进程(Daemon),导致无法激活前端进程(CGError -606对应kCGErrorNotActivated,提示appIsDaemon)。以下是具体修复方案:
改用标准macOS App项目结构
当前代码是直接运行NSApplication的命令行式逻辑,没有完整的App Bundle,系统会判定为非GUI应用。需创建标准的macOS App项目,将业务逻辑迁移到AppDelegate或SwiftUI生命周期框架中,确保应用有正常的GUI身份。修正窗口使用方式
临时创建的极小无边界窗口无法被系统正确识别为GUI窗口载体,建议直接使用应用的主窗口调用showDefinition:func ShowWordDefinition(){ DispatchQueue.main.async { guard let text = NSPasteboard.general.string(forType: .string), let mainWindow = NSApp.mainWindow, let contentView = mainWindow.contentView else { return } let attributedString = NSAttributedString(string: text) // 转换鼠标位置到主窗口坐标系 let mouseLocation = NSEvent.mouseLocation let windowPoint = contentView.convert(mouseLocation, from: nil) contentView.showDefinition(for: attributedString, at: windowPoint) } }检查应用激活权限配置
查看Info.plist,如果存在LSUIElement键且值为YES,会让应用后台运行无法激活前端,需移除该键或设为NO;同时确认辅助功能权限已正确生效。优化全局事件监听的上下文
全局键盘监控的回调执行上下文可能存在异常,建议改用应用内快捷键监听(如NSMenuItem绑定快捷键),或确保调用showDefinition时,应用主窗口已创建并处于可激活状态。
内容的提问来源于stack exchange,提问作者WOTMCCR

