【问题标题】:NSTextView not updating after Image insert图片插入后 NSTextView 不更新
【发布时间】:2016-05-26 10:01:44
【问题描述】:

我的应用程序(swift、OSX、Xcode、所有东西的最新版本)有一个 NSTextView,我允许用户输入。 NSTextView 启用了 RichText、图形和 NSInspectorBar。

我将 NSTextView 的内容加载/保存为 webarchive 格式(grumble grumble - 但我需要一种包含图像的可移植格式)。

到目前为止一切顺利。一切正常……除了一个小细节。当我将图像插入 TextView 时,它不会显示出来。但它就在那里,因为如果我保存并加载......它就会出现。

这是我将图像插入 NSTextView 的方法(我从 NSOpenPanel 获取图像的路径:

    guard let theImage = NSImage(contentsOfURL: openPanel.URL!) else   {
        showErrorMessage("Unable to load image")
        return
    }
    // self.textEditor is the NSTextView
    guard let store = self.textEditor.textStorage else { abort() }

    let attachment = NSTextAttachment()
    attachment.image = theImage
    let attrString = NSAttributedString(attachment: attachment)       

    let range = self.textEditor.selectedRange()
    store.replaceCharactersInRange(range, withAttributedString: attrString)

我认为它相当简单:加载图像,添加到属性字符串,用属性字符串替换选定的字符。

但是什么也没有出现。 NSTextView 完全没有变化。如果我将 NSTextStorage 内容保存为 webarchive:

    guard let store = textEditor.textStorage else { abort() }
    let attr: [String: AnyObject] = [NSDocumentTypeDocumentAttribute: NSWebArchiveTextDocumentType]
    let data = try store.dataFromRange(NSMakeRange(0, store.length), documentAttributes: attire)
    //... save 'data' to DB ...

然后重新加载它们:

    //... load 'data' from the DB ...
    guard let store = textEditor.textStorage else { abort() }
    let str = try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute:NSWebArchiveTextDocumentType], documentAttributes: nil)
    store.setAttributedString(str)

...图像出现在正确的位置。

我对这个很困惑。有人对我缺少什么有任何想法吗?

顺便说一句 - 我尝试使用以下命令强制刷新:

let frame = self.textEditor.frame
self.textEditor.setNeedsDisplayInRect(frame)

那没用。

感谢您提供的任何建议。 干杯。 保罗

编辑:附录...我一直在弄乱 NSTextAttachmentCells,希望它们可以工作。它们以完全不同的方式失败。

如果我只是将上面的图片插入代码替换为:

    let cell = NSTextAttachmentCell(imageCell: theImage)
    let txtAtt = NSTextAttachment()
    txtAtt.attachmentCell = cell
    let str = NSAttributedString(attachment: txtAtt)
    let range = self.textEditor.selectedRange()
    store.replaceCharactersInRange(range, withAttributedString: str)

...然后图像确实会在插入后立即出现,并且在正确的位置。但他们没有得救!也就是说,当我保存并重新加载(根据上面的代码)时,它们不会包含在 webarchive 中。

编辑^2: 因此,从上面得出的明显结论是,将图像附加到 TextAttachment 将图像附加到 NSTextAttachmentCell,它也附加到 TextAttachment。嗯……这行不通。但是起作用的是:

    let cell = NSTextAttachmentCell(imageCell: theImage)
    let txtAtt = NSTextAttachment(data: theImage.TIFFRepresentation, ofType: kUTTypeTIFF as String)
    txtAtt.attachmentCell = cell
    //txtAtt.image = theImage
    let str = NSAttributedString(attachment: txtAtt)
    let rng = self.textEditor.selectedRange()
    store.replaceCharactersInRange(rng, withAttributedString: str)

也就是说...我创建了一个 TextAttachment,传递图像的 TIFF 表示形式的数据。我还创建了 AttachmentCell。这现在有效 - 插入可见并保存。

唯一的缺点是 TIFF 非常大 - 图像扩展为内存大小的 3 倍。

任何人都可以提供一些关于为什么会这样的想法吗?

【问题讨论】:

    标签: swift macos


    【解决方案1】:

    好的,这就是解决方案。

    NSTextAttachmentCell 代表

    ...绘制文本附件图标并在其图标上处理鼠标事件的对象接口apple docs

    因此,您需要使用图像创建其中之一。

    NSTextAttachment

    ...包含一个 NSData 对象或一个 NSFileWrapper 对象,后者又包含附加文件apple docs的内容

    所以你需要两者 - 一个用于显示和交互,一个用于保存(即实际数据)。我在保存 TIFF(太大)时遇到的问题可以通过创建 JPG 或 PNG 表示来解决,它们可以很高兴地用于 NSData 对象。我通过扩展 NSImage 来做到这一点:

    extension NSImage {
        var imagePNGRepresentation: NSData {
            return NSBitmapImageRep(data: TIFFRepresentation!)!.representationUsingType(.NSPNGFileType, properties: [:])!
        }
        var imageJPGRepresentation: NSData {
            return NSBitmapImageRep(data: TIFFRepresentation!)!.representationUsingType(.NSJPEGFileType, properties: [:])!
        }
    }
    

    (感谢来自here 的评论者关于如何做到这一点)。

    所以这里是实际上可以将图像插入到 NSTextView 中的代码(请打鼓)...

    guard let theImage = NSImage(contentsOfURL: openPanel.URL!) else {
        showErrorMessage("Unable to load image")
        return
    }
    guard let store = self.textEditor.textStorage else { abort() }
    
    let cell = NSTextAttachmentCell(imageCell: theImage)
    let txtAtt = NSTextAttachment(data: theImage.imageJPGRepresentation, ofType: kUTTypeJPEG as String)
    txtAtt.attachmentCell = cell
    let str = NSAttributedString(attachment: txtAtt)
    let range = self.textEditor.selectedRange()
    store.replaceCharactersInRange(range, withAttributedString: str)
    

    当我将其保存为 webarchive 时,我可以看到 JPG 对象与 HTML 一起保存。

    扩展这个...您可能可以插入任何数据类型(例如文档)并在单元格中使用图标表示。很酷。

    奇怪的是,大多数描述此内容的网页都不包含 Cell。老实说,我不知道它是如何工作的。

    干杯。 保罗。

    【讨论】:

    • 最后一点...似乎 NSTextAttachmentCell 在 OSX 上是必需的。来自文档:在 OS X 上,文本附件还使用符合 NSTextAttachmentCell 协议的单元格对象来绘制和处理鼠标事件
    • 我欠你的一切
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2017-04-08
    • 2011-07-15
    • 1970-01-01
    相关资源
    最近更新 更多