当我单击 AppKit 的 showDefinition(for:at) 函数生成的视图时,我的 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
我已经包含了创建视图的函数片段:
func ShowDefinition(selectedText : String) {
DispatchQueue.main.async {
let DefinitionWindow = NSWindow(contentRect: NSRect(origin: self.mouseLocation, size: NSSize(width: 1, height: 1)), styleMask: [.borderless], backing: .buffered, defer: false)
DefinitionWindow.level = .floating
guard let mainScreenFrame = NSScreen.main?.frame else {
return
}
DefinitionWindow.contentView?.showDefinition(for: attributedString, at: pointInWindow)
DefinitionWindow.orderFront(nil)
}
}
潜在的问题和疑虑:
是否存在与 UI 转换或主线程相关的问题?
showDefinition(for:at) 流程在内部到底是如何工作的?
也许,点击时视图的显示级别提升导致了冲突?
如果有人可以提供解决此问题的任何见解或指导,我们将不胜感激。谢谢!
感谢您协助解决我的疑问并提供宝贵的见解。对于我最初提供的不完整的代码,我深表歉意。下面是一个完整且可重现的代码片段,可以在终端项目模板中直接执行。请注意,它需要在隐私设置中授予辅助权限。
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()