在macOS 10.14上键入文本时,NSTextView光标没有出现 [英] NSTextView cursor doesn't appear when typing text on macOS 10.14

查看:74
本文介绍了在macOS 10.14上键入文本时,NSTextView光标没有出现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用NSTextView的macOS 10.12 Mojave上观察到一个奇怪的问题.

I'm observing a strange issue on macOS 10.12 Mojave with NSTextView.

.

我正在像这样更改 didChangeText()中的textStorage属性:

I'm changing the textStorage attributes in didChangeText() like this :

self.textStorage?.beginEditing()

ARTokenManager.getToken(text: text, language: language) { (tokens) in
    // This line reset the attributes
    // If I remove it, the cursor appear properly
    // But the attributes are conserved 
    self.textStorage?.setAttributes([NSAttributedString.Key.font: self.font!,
                                     NSAttributedString.Key.foregroundColor: self.defaultTextColor], range: range)
    for token in tokens {
        let attributeRange = NSRange(location: token.range.location + range.location, length: token.range.length)
        self.textStorage?.addAttributes(token.attributes, range: attributeRange)
    }
}

self.textStorage?.endEditing()

当我删除 setAttributes 方法时,一切都按预期工作,但我无法解释原因.我可能将属性重置错误.此问题仅适用于Mojave.

When I remove the setAttributes method, everything works as expected, but I can't explain why. I'm possibly resetting the attributes wrong. This issue only works with Mojave.

有人有同样的问题或可以向我解释我在做什么错吗?

Does someone have the same issue or can explain me what I'm doing wrong ?

谢谢.

推荐答案

经过研究,我发现我的问题更多是关于使用NSTextView突出显示语法.我知道这是很多macOS开发人员都在问的一个问题,并且有很多解决方案.这可能不是最好的方法,但这就是我解决此问题的方法.

After some research, I discovered that my question was more about syntax highlighting with NSTextView. I know this is a question that a lot of macOS developers are asking about and there are a lot of solutions for that. This is not probably the best one, but this is how I’ve solved this problem.

为此,我使用了NSTextStorage的子类.这是完成所有语法工作的地方.NSTextStorage不是面向协议的,因此您必须按照Apple文档的建议自己重写方法:

To achieve that, I’ve used a subclass of NSTextStorage. This is where all the syntax work will be done. NSTextStorage is not protocol oriented so you have to override method by yourself as the Apple documentation suggest :

class SyntaxTextStorage: NSTextStorage {

    private var storage: NSTextStorage

    override var string: String {
        return storage.string
    }

    override init() {
        self.storage = NSTextStorage(string: "")
        super.init()
    }

    override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key : Any] {
        return storage.attributes(at: location, effectiveRange: range)
    }

    override func replaceCharacters(in range: NSRange, with str: String) {
        beginEditing()
        storage.replaceCharacters(in: range, with: str)
        edited(.editedCharacters, range: range, changeInLength: str.count - range.length)
        endEditing()
    }

    override func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange) {
        beginEditing()
        storage.setAttributes(attrs, range: range)
        edited(.editedAttributes, range: range, changeInLength: 0)
        endEditing()
    }

}

这是创建文本存储的基础.

This is the basic to create your text storage.

下一步是将文本存储设置为textView.为此,可以使用textView layoutManager 中可访问的 replaceTextStorage()方法.

The next step is to set your text storage into your textView. To do so, you can use the replaceTextStorage() method accessible in the textView layoutManager.

class SyntaxTextView: NSTextView {

    var storage: SyntaxTextStorage!

    override func awakeFromNib() {
        super.awakeFromNib()
        configureTextStorage()
    }

    private func configureTextStorage() {
        storage = SyntaxTextStorage()
        layoutManager?.replaceTextStorage(storage)
    }

}

语法

最后一步是完成语法工作.此过程的CPU成本非常高.有很多方法可以做到最好.我建议您实现一个类,该类将为您返回 NSAttributedString NSRange 的列表.文本存储的工作仅应将样式应用于文本.我个人使用 processEditing 方法执行文本分析:

Syntaxing

The final step is to do your syntax job. The CPU cost of this process is very hight. There is a lot of way to do it to have the best performances. I suggest you to implement a class that will returns you a list of NSAttributedString and NSRange. The job of the text storage should only be applying the style to your text. Personally, I've used the processEditing method to perform my text analyze :

override func processEditing() {
    super.processEditing()
    syntaxCurrentParagraph()
}

我建议您在后台进行语法分析,然后,如果自上次分析以来没有文本更改,请将更改应用于文本.始终在文本存储区中,我实现了一个 syntax 方法,该方法将样式应用于文本:

I recommend you to do you syntax analyze in background, then, if there is no text change since your last analyze, apply the change to your text. Always in my text storage, I've implemented a syntax method that apply the style to the text :

private func syntax(range: NSRange, completion: ((_ succeed: Bool) -> Void)? = nil) {
    guard range.length > 0 else {
        completion?(true)
        return
    }

    // Save your data to do the job in background
    let currentString = self.string
    let substring = currentString.substring(range: range)
    let mutableAttributedString = NSMutableAttributedString(string: substring, attributes: NSAttributedString.defaultAttributes as [NSAttributedString.Key : Any])

    DispatchQueue.global(qos: .background).async {
        ARSyntaxManager.tokens(text: substring, language: self.language) { (tokens) in
            // Fill you attributed string
            for token in tokens {
                mutableAttributedString.addAttributes(token.attributes, range: token.range)
            }

            DispatchQueue.main.async {
                // Check if there is no change
                guard self.string.count == currentString.count else {
                    completion?(false)
                    return
                }

                completion?(true)

                // Apply your change
                self.storage.replaceCharacters(in: range, with: mutableAttributedString)
                self.displayVisibleRect()
            }
        }
    }
}

就是这样.希望对您有所帮助.

That's it. Hope it will help some of you.

这篇关于在macOS 10.14上键入文本时,NSTextView光标没有出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆