用 NSTextAttachment 替换 UILabel 中的表情符号 - copying/pasting 无法将明文表示设置回常规表情符号

Replacing emoji within UILabel with NSTextAttachment - not able to set the plaintext representation back to regular emoji for copying/pasting

我正在用我自己的自定义表情符号替换 UILabel/UITextView 中的表情符号。这很好用,但我正在努力解决的问题是粘贴原始表情符号。

因此,例如 UILabel 可能会显示 "Hello ",带有自定义表情符号,复制然后粘贴该文本,或者调用 UILabel 的 text 属性 将显示 "Hello " 使用标准表情符号。

我正在使用显示图像的 NSTextAttachment 的子类实现此功能,并在使用表情符号时将其添加为 NSAttributedString:

class EmojiTextAttachment: NSTextAttachment {
    static let size = CGSize(width: 16, height: 16)

    let emoji: Emoji

    init(emoji: Emoji) {
        self.emoji = emoji

        super.init(data: emoji.rawValue.data(using: .utf8), ofType: "public.text")
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func image(forBounds imageBounds: CGRect, textContainer: NSTextContainer?, characterIndex charIndex: Int) -> UIImage? {
        return Emoji.generateConstrainedFaceImage(emoji: emoji, height: imageBounds.size.height)
    }
}

let emoji = Emoji(rawValue: emojiString)!
let emojiTextAttachment = EmojiTextAttachment(emoji: emoji)
emojiTextAttachment.bounds = CGRect(x: 0, y: self.font!.descender, width: self.font!.lineHeight, height: self.font!.lineHeight)    
let attributedString = NSAttributedString(attachment: emojiTextAttachment)

这显示正确,但现在如果我调用 UITextField 的 text 属性,它不会将 NSTextAttachment 作为其文本的一部分。此外,复制内容会将 EmojiTextAttachment 复制为数据。在这里,我试图将 data:ofType: 设置为一个字符串(转换为数据),但这没有用,它只是形成了一些被粘贴的数据。通过 emojiTextAttachment.image 设置图像意味着它会粘贴图像。通过 imageForBounds:textContainer:characterIndex: 函数设置它意味着图像本身不会得到 copied/pasted.

有没有一种方法可以设置 NSTextAttachment 的明文表示形式,或者其他已知的实现方法?

找不到真正干净的方法。不支持子类化 NSAttributedString,因此无法覆盖 string 函数。

相反,我添加了一个带有 plaintextRepresentation 函数的 NSAttributedString 扩展,它通过属性枚举,用表情符号本身替换任何 EmojiTextAttachments,然后 returns string属性字符串的值。