Thank you very much for the answer. Let me explain in details what I'm trying to achieve:
1. I'm finishng an application which requires syntax highlight. It's written in Swift. I'm using flex to find tokens and iterrating through them inside the NSTextStorageDelegate method:
optional func textStorage(_ textStorage: NSTextStorage,
didProcessEditing editedMask: NSTextStorageEditActions,
range editedRange: NSRange,
changeInLength delta: Int)
2. Whenever I find a token I'm changing the foreground color using setAttribute(_:_:_:). As you can imagine this is the bottle neck, especially with big text files.
3. The NSLayoutManager is NOT noncontiguous. I tried turning noncontiguous mode to TRUE, but whenever I change even a single attribute, the entire layout management starts to behave not correcty. For example if I have 5-6 new lines and press backspace - the carret goes 3-4 lines above it's current position and stays there for a while, no matter what keys are pressed ... and on insert the scroll bars are jumping .. i.e. the entire text view. If you know please advise where is safe to change attributes when having noncontiguous mode enabled (I tried during the other delegate method - willProcessEditing ... nothing changed).
4. I subclasses NSTextSorage. It's pretty much exactly the way Apple advised in their documentation. Here is the class:
class myTextStorage: NSTextStorage {
private var storage: NSTextStorage
override var string: String { return storage.string }
// override var fixesAttributesLazily: Bool { get { return true } }
override init() {
storage = NSMutableAttributedString()
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
required init?(pasteboardPropertyList propertyList: AnyObject, ofType type: String) {
fatalError("init(pasteboardPropertyList:ofType:) has not been implemented")
}
override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String : AnyObject] {
return storage.attributesAtIndex(location, effectiveRange: range)
}
override func replaceCharactersInRange(range: NSRange, withString str: String) {
storage.replaceCharactersInRange(range, withString: str)
edited(.EditedCharacters, range: range, changeInLength: str.utf16.count - range.length)
}
override func setAttributes(attrs: [String : AnyObject]?, range: NSRange) {
storage.setAttributes(attrs, range: range)
edited(.EditedAttributes, range: range, changeInLength: 0)
}
}
Unfortunately it works with small texts. In the moment I pase 4 MBytes of text - everything crashes .... and I mean everything, including the macOS. And this is happeneing before ever going into didProcessEditing method.
I know that I need to highlight smaller portions of text, which can be handeled very quickly. What I'm looking for is advise how to lazily set the attributes. What you mentioned may be the right way. May I ask you to explain in more details what you mean?
If you want you can reach me via ivailon at gmail dot com for specifics regarding the app.