SwiftUI中NSFontPanel颜色选择器取值异常及隐藏方案咨询
问题解决方案
你可以根据需求二选一实现:
方案1:直接隐藏字体面板的颜色选择器(无额外逻辑成本,推荐不需要颜色功能时使用)
直接在唤起字体面板的代码中移除面板的颜色选项即可,使用系统公开API,无兼容问题:
在你按钮点击逻辑里的fontPanel.orderBack(nil)行之前添加以下代码:
// 移除面板的颜色选择区块 fontPanel.panelOptions.remove(.color)
添加后颜色选择器会直接从字体面板中消失,不需要处理任何颜色相关逻辑,原有字体、字号、样式功能不受影响。
方案2:实现颜色选择器的正常取值
你当前无法获取选中颜色的核心原因有两点:
- 调用
fontManager.convertAttributes时传入了空字典,该方法需要传入当前已有的属性字典作为转换基准,传入空值时不会返回面板选中的颜色属性 - 颜色选择器的交互默认不会触发你绑定给NSFontManager的
changeAttributes回调,需要手动绑定NSColorPanel的响应事件
具体修改步骤:
- 首先给NSColorPanel绑定回调,在按钮点击唤起面板的代码块中,添加以下两行,确保选色时触发你的代理方法:
NSColorPanel.shared.target = self.fontPickerDelegate NSColorPanel.shared.action = #selector(fontPickerDelegate?.changeAttributes)
- 修改
fontSelected方法的属性转换逻辑,不要传入空字典,而是传入当前已有的字体、颜色属性作为转换基准,修改后的代码如下:
func fontSelected() { // 原有字体、字号获取逻辑保持不变 self.font = fontPanel.convert(self.font) setSidebarFont = self.font.displayName ?? "System" setSidebarFontSize = Int(self.font.pointSize) // 构造当前已有的属性字典作为转换基准,不要传空字典 // 注意:此处的初始颜色请替换为你实际存储的当前字体颜色 let currentColor = NSColor(calibratedWhite: 0.5, alpha: 1) // 示例灰色,替换为你的实际值 var currentAttrs: [NSAttributedString.Key: Any] = [ .font: self.font, .foregroundColor: currentColor, .underlineStyle: NSUnderlineStyle.single.rawValue, // 替换为你当前的下划线设置 .strikethroughStyle: NSUnderlineStyle.single.rawValue // 替换为你当前的删除线设置 ] // 传入当前属性获取转换后的完整属性 let newAttributes = fontManager.convertAttributes(currentAttrs) // 此时即可正确获取选中的字体颜色 if let selectedFontColor = newAttributes[.foregroundColor] as? NSColor { // 处理颜色存储逻辑,注意不要用字符串存储颜色,建议通过NSKeyedArchiver将NSColor转为Data存入AppStorage,避免颜色值丢失 print("选中的字体颜色:\(selectedFontColor)") } // 下划线、删除线等属性也可以从newAttributes中正常获取 if let underline = newAttributes[.underlineStyle] as? Int { // 处理下划线样式更新 } if let strikethrough = newAttributes[.strikethroughStyle] as? Int { // 处理删除线样式更新 } }
注意:你当前用字符串
"gray"存储字体颜色的方式可靠性很差,大部分自定义颜色、系统动态颜色无法通过字符串准确序列化,建议改用归档后的Data类型存储NSColor对象。
内容的提问来源于stack exchange,提问作者Frank Nichols
相关产品推荐
相关产品推荐

