问题描述
我有一个自定义的 NSTextView
子类,它显示一个或多个表示令牌的 NSTextAttachment
对象(类似于 NSTokenField
)。
问题是 contents
上的 NSTextAttachment
属性在从粘贴板读取 NSAttributedString
后始终为零,即使我看到此数据正在保存到粘贴板。>
- 创建文本附件并将其插入文本存储
let attachmentData = "\(key):\(value)".data(using: .utf8)
let attachment = NSTextAttachment(data: attachmentData,ofType: kUTTypeUTF8PlainText as String)
attachment.attachmentCell = CustomAttachmentCell(key: key,value: value)
...
textStorage.replaceCharacters(in: range,with: NSAttributedString(attachment: attachment))
-
CustomAttachmentCell
是一个标准的NSTextAttachmentCell
子类,只处理自定义绘图。它按预期在文本视图中绘制文本附件,并使用标准 CoreGraphics API 调用为附件的视觉表示绘制背景和文本。
class CustomAttachmentCell: NSTextAttachmentCell {
let key: String
let value: String
override func draw(withFrame cellFrame: NSRect,in controlView: NSView?) {
drawKey(withFrame: cellFrame,in: controlView)
drawValue(withFrame: cellFrame,in: controlView)
}
}
- 配置
NSTextViewDelegate
方法来处理将附件写入粘贴板
// If the prevIoUs method is not used,this method and the next allow the textview to take care of attachment dragging and pasting,with the delegate responsible only for writing the attachment to the pasteboard.
// In this method,the delegate should return an array of types that it can write to the pasteboard for the given attachment.
func textView(_ view: NSTextView,writablePasteboardTypesFor cell: NSTextAttachmentCellProtocol,at charIndex: Int) -> [NSPasteboard.PasteboardType] {
return [(kUTTypeFlatRTFD as NSPasteboard.PasteboardType)]
}
// In this method,the delegate should attempt to write the given attachment to the pasteboard with the given type,and return success or failure.
func textView(_ view: NSTextView,write cell: NSTextAttachmentCellProtocol,at charIndex: Int,to pboard: NSPasteboard,type: NSPasteboard.PasteboardType) -> Bool {
guard type == kUTTypeFlatRTFD as NSPasteboard.PasteboardType else { return false }
guard let attachment = cell.attachment else { return false }
return pboard.writeObjects([NSAttributedString(attachment: attachment)])
}
- 在文本视图中右键单击文本附件并从上下文菜单中选择“剪切”后,我可以使用 Clipboard Viewer.app 在粘贴板中看到 RTFD 数据:
rtfd............
...Attachment.........TXT.rtf....M...÷...........exampleKey:exampleValue....E.......
...Attachment....TXT.rtf..........Ñ`¶...........².Ñ`¶...............ï...{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0
\f0\fs24 \cf0 {{\NeXTGraphic Attachment \width640 \height640 \appleattachmentpadding0 \appleembedtype0 \appleaqc
}¬}\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0
\cf0 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0
\cf0 {{\NeXTGraphic Attachment \width640 \height640 \appleattachmentpadding0 \appleembedtype0 \appleaqc
}¬}}
override func textStorageWillProcessEditing(_ notification: Notification) {
guard let attributedString = notification.object as? NSAttributedString else { return }
attributedString.enumerateAttribute(.attachment,in: NSRange(location: 0,length: attributedString.length),options: [],using: { (value,range,stop) in
if let attachment = value as? NSTextAttachment {
// attachment.contents is nil here,I was expecting a Data object representing the UTF-8 string "exampleKey:exampleValue"
}
})
}
或者,我尝试在我的 NSTextView
子类中覆盖一些与粘贴板相关的方法来做同样的事情(读/写 rftd 数据)。
- 覆盖
readablePasteboardTypes()
以重新排序,以便最丰富的数据(例如 com.apple.flat-rtfd / NeXT RTFD 粘贴板类型)排在数组的首位。 - 覆盖
preferredPasteboardType(from: restrictedToTypesFrom:)
以返回(kUTTypeFlatRTFD as NSPasteboard.PasteboardType)
- 覆盖
readSelection(from:type:)
当覆盖上述方法时,我会看到相同的行为:
- 从粘贴板上读取
NSAttributedString
- 枚举属性字符串中包含的
NSTextAttachment
对象 - 枚举的
NSTextAttachment
对象contents
属性始终设置为 nil 而不是Data
表示写入NSTextAttachment
内的粘贴板的 UTF-8 字符串“exampleKey:exampleValue” {1}} 位于NSAttributedString
内。
这似乎是一个相当深奥的问题,因为我发现的所有示例代码和搜索结果都使用 NSFileWrapper
或 NSImage
/UIImage
来支持他们的 {{1 }} 而不是 NSTextAttachment
初始值设定项。
谢谢!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)