自定义NSTextStorage:表情符号默认不显示

时间:2016-09-10 21:31:59

标签: fonts emoji nstextview textkit nstextstorage

我在自定义NSTextStorage子类中遇到表情符号问题。该类不存储传递给它的任何属性。相反,它会生成自己的:

override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String : AnyObject] {
    if range != nil {
        range.memory = NSMakeRange(0, self.string.length)
    }

    let attributes = [
        NSFontAttributeName: NSFont.systemFontOfSize(14)
    ]

    return attributes
}

override func setAttributes(attrs: [String : AnyObject]?, range: NSRange) {
    // does nothing
}

这大部分工作正常。但是,如果字符串中有任何表情符号,它们就不会显示出来。在检查NSTextView对文本存储进行的调用时,看起来文本视图会尝试将任何表情符号范围的字体属性设置为AppleColorEmoji字体。如果您依靠文本视图作为"属性真相的来源,这很好,但我不希望我的程序像这样工作。在我的例子中,文本存储需要是任何属性的唯一供应商。它不能听取文本视图发送的任何内容,属性方面。

我是否必须手动检测字符串中的任何表情符号并手动设置AppleColorEmoji字体?或者,还有更好的方法?我已经尝试过使用后备字体并自动搜索包含缺失字符的字体,但似乎没有使用这些方法覆盖表情符号。

1 个答案:

答案 0 :(得分:3)

想出来。简而言之,归因字符串(以及因此文本存储)在编辑之后调用fixAttributesInRange(range: NSRange)以便整理用于呈现的属性,例如,在需要的地方添加表情符号字体。反过来,fixAttributesInRange会调用setAttributes(attrs: [String : AnyObject]?, range: NSRange)来提交这些额外的属性。这意味着您不能仅仅从attributesAtIndex(location: Int, effectiveRange range: NSRangePointer)出售本地构造的字典:您必须跟踪这些“固定”属性,否则您的字符串将在某些情况下中断。

不幸的是,setAttributes还从文本视图中接收属性,我们要忽略这些属性。幸运的是,通过这样做很容易解决这个问题:

override func fixAttributesInRange(range: NSRange) {
    self.isFixingAttributes = true
    super.fixAttributesInRange(range)
    self.isFixingAttributes = false
}

...然后检查isFixingAttributes中的setAttributes标记。这样,文本存储只会记录“固定”属性,而不会从外部记录任何属性。

相关问题