我发现字符串着色的时间取决于使用了多少种不同的NSColors。在下面的代码中,如果我只对三种情况使用一种颜色,则文本着色过程比三种不同颜色用于这三种情况的情况快3倍,每种情况下每种颜色。为什么?有没有办法不减慢三种不同颜色的着色?
for i in 0..<arrayOfNSRangesForA.count
{
textFromStorage.addAttribute(NSForegroundColorAttributeName, value: NSColor.green, range: arrayOfNSRangesForA[i])
}
for i in 0..<arrayOfNSRangesForT.count
{
textFromStorage.addAttribute(NSForegroundColorAttributeName, value: NSColor.green, range: arrayOfNSRangesForT[i])
}
for i in 0..<arrayOfNSRangesForC.count
{
textFromStorage.addAttribute(NSForegroundColorAttributeName, value: NSColor.green, range: arrayOfNSRangesForC[i])
}
更新
我发现了一件坏事。当我将着色从NSForegroundColorAttributeName
更改为NSBackgroundColorAttributeName
时,运行时间显着增加了10倍。对于20 000个字符,对于NSForegroundColorAttributeName
- 1秒,对于NSBackgroundColorAttributeName
- 10秒,它是一种颜色;如果有三种颜色 - 相应的3和30秒。对我而言,Swift的功能非常糟糕!由于DNA的长度是数千个A,T,G,C字符,因此无法用DNA(ATGC序列)着色进行正常工作!
更新 在评论中,我建议只为文本的可见部分着色。我尝试过这种方法,与标准方式相比,即使对于较短的文本也是如此。所以,我有文本的NSRange文本的可见部分,并在滚动时使用通知滚动时在飞行中着色。这是一个糟糕的方式。
答案 0 :(得分:2)
最大的障碍是在文本视图中列出所有这些属性字符。将DNA序列着色需要最少的时间。您可以采用分而治之的方法,而不是编写自己的布局管理器或文本存储类,而是通过一次一块地对文本视图进行着色:
@IBOutlet var textView: NSTextView!
var dnaSequence: String!
var attributedDNASequence: NSAttributedString!
@IBAction func colorize(_ sender: Any) {
self.dnaSequence = "ACGT" // your plaintext DNA sequence
self.attributedDNASequence = self.makeAttributedDNASequence()
// Rendering long string with the same attributes throughout is extremely fast
self.textView.textStorage?.setAttributedString(NSAttributedString(string: dnaSequence))
let step = 10_000 // colorize 10k characters at a time
let delay = 0.2 // delay between each render
for (i, location) in stride(from: 0, to: self.dnaSequence.characters.count, by: step).enumerated() {
let length = min(step, self.dnaSequence.characters.count - location)
let range = NSMakeRange(location, length)
// Since we are modifying the textStorage of a GUI object (NSTextView)
// we should do it on the main thread
DispatchQueue.main.asyncAfter(deadline: .now() + (delay * Double(i))) {
let subtext = self.attributedDNASequence.attributedSubstring(from: range)
print("Replacing text in range \(location) to \(location + length)")
self.textView.textStorage?.replaceCharacters(in: range, with: subtext)
}
}
}
// MARK: -
var colorA = NSColor.red
var colorC = NSColor.green
var colorG = NSColor.blue
var colorT = NSColor.black
func makeAttributedDNASequence() -> NSAttributedString {
let attributedText = NSMutableAttributedString(string: dnaSequence)
var index = dnaSequence.startIndex
var color: NSColor!
for i in 0..<dnaSequence.characters.count {
switch dnaSequence[index] {
case "A":
color = colorA
case "C":
color = colorC
case "G":
color = colorG
case "T":
color = colorT
default:
color = NSColor.black
}
attributedText.addAttribute(NSForegroundColorAttributeName, value: color, range: NSMakeRange(i,1))
index = dnaSequence.index(after: index)
}
return attributedText
}
诀窍是使应用程序尽可能响应,以便用户不知道事情仍在后台完成。使用较小的delay
(&lt; = 0.3秒),我无法快速滚动鼠标到达文本视图的末尾,然后才能对所有内容进行着色(100k字符)。
在一个100k字符的测试中,花了0.7秒直到彩色字符串首次出现在文本视图中,而不是7秒,如果我一次完成所有内容。
答案 1 :(得分:-1)
您是否尝试使用ciColor
而不是属性? ciColors
可用于文字,图片和背景。
您可以尝试这样:
txtField.textColor?.ciColor.red