Last active
July 1, 2023 10:14
-
-
Save soffes/23e67046a749258454578ff886614e29 to your computer and use it in GitHub Desktop.
Fast, concrete text storage intended to be subclassed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
/// Fast, concrete text storage intended to be subclassed. | |
class BaseTextStorage: NSTextStorage { | |
// MARK: - Properties | |
private let storage = NSMutableAttributedString() | |
// MARK: - NSTextStorage | |
override var string: String { | |
return storage.string | |
} | |
override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key: Any] { | |
assert(location < length, | |
"Tried to access attributes at out of bounds index \(location). Length: \(length)") | |
return storage.attributes(at: location, effectiveRange: range) | |
} | |
override func replaceCharacters(in range: NSRange, with string: String) { | |
assert(NSMaxRange(range) <= length, | |
"Tried to replace characters at out of bounds range \(range). Length: \(length)") | |
let stringLength = (string as NSString).length | |
if range.length == 0 && stringLength == 0 { | |
return | |
} | |
beginEditing() | |
storage.replaceCharacters(in: range, with: string) | |
edited(.editedCharacters, range: range, changeInLength: stringLength - range.length) | |
endEditing() | |
} | |
override func setAttributes(_ attributes: [NSAttributedString.Key: Any]?, range: NSRange) { | |
assert(NSMaxRange(range) <= self.length, | |
"Tried to set attributes at out of bounds range \(range). Length: \(length)") | |
beginEditing() | |
storage.setAttributes(attributes, range: range) | |
edited(.editedAttributes, range: range, changeInLength: 0) | |
endEditing() | |
} | |
} |
@dasmer so it works on both :)
Keep in mind that replacing the NSMutableAttributedString
with a NSTextStorage
instance as backing storage speeds up things tremendously.
@DivineDominion you can't initialize one directly per the documentation. That's why this class exists.
How did you measure speed up here? From what I see, NSMutableAttributedString
is significantly slower than NSTextStorage. Especially when using with Swift (See https://bugs.swift.org/browse/SR-6197)
@krzyzanowskim interesting. I talked with the Swift folks about this years ago and my understanding was this was fixed. If that's not the case, use the Objective-C version instead.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why import
UIKit
/AppKit
here?