2017-01-31 10 views
8

문자열 색칠의 시간은 얼마나 많은 다른 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 초 동안 1 색이었습니다. 3 색이면 3 초 ~ 30 초. 나를 위해 그것은 Swift의 매우 나쁜 특징이다! !! DNA의 길이가 A, T, G, C 문자의 수천이기 때문에 DNA (ATGC 시퀀스) 채색으로 정상적인 작업을 수행 할 수 없습니다!

업데이트 의견에서 나는 보이는 부분 만 색칠을 제안합니다. 나는이 방법을 시도해 보았고, 표준적인 방법으로했던 것과 비교해 짧은 텍스트라도 훨씬 더 나쁘다. 그래서, 텍스트의 보이는 부분에 대해 텍스트의 NSRange를 가지며, 스크롤이 켜져있을 때 알림을 사용하여 스크롤하는 동안 파리에서 색칠했습니다. 그것은 나쁜 방법입니다.

+0

색상이 적용되는 특정 범위에 따라 동일한 속성의 실행이 하나가 될 수 있습니다. 또는 차이 색상을 사용할 때보 다 실행 횟수가 적습니다. 각 작업에 대한 오버 헤드가있는 실행마다 별도의 그리기 작업이 있습니다. 'enumerateAttributes (in : options : using :) '을 사용하여 각각의 경우에 얼마나 많은 실행이 있는지 확인할 수 있습니다. –

+0

@Ken Thomases 필자는 A, G, T 및 C 문자가 서로 다른 양으로 구성된 약 180,000 자의 문자열을 테스트했지만 실제로는 DNA 시퀀스입니다. 먼저 각 A, G, T 및 C의 범위를 결정합니다. 따라서 범위가 4 개 배열 된 다음 A, G, T 및 C 문자에 색상을 지정합니다. – VYT

+0

@Ken Thomases는 각 C, G, A 및 T의 배열이 동일하기 때문에 하나의 색상 또는 3 개의 색상에 대해 범위의 병합은 채색 과정에서만 발생할 수 있으며, 각 루프마다 다른 루프에 의존 ?? – VYT

답변

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 (< = 0.3 초)을 사용하면 모든 것이 색으로 구분되기 전에 텍스트보기 끝까지 충분히 빠르게 스크롤 할 수 없었습니다 (100k 문자).

100k 문자 테스트에서 한 번에 모든 작업을 수행하면 색상이 지정된 문자열이 텍스트보기 내부에 표시 될 때까지 7 초가 아닌 7 초가 걸렸습니다.

+0

답변 해 주셔서 감사합니다! 아니요, 저는 코드 에서처럼 setAttributedString을 배치했습니다. 차이점은 A, T, C 각각에 대한 NSRanges의 첫 번째 발견과 '스위치'를 사용하지 않는 채색입니다. 나는 두 개의 문자열을 정렬 한 다음 결합 된 문자열을 채색합니다. 그래서, 나는 문자열 길이에 대해 약간 잘못 작성했습니다. 저는 각각 약 20,000 개를 사용했습니다. 그래서 결합 된 문자열은 약 40 000이며 약 3 초입니다. 귀하의 코드 (나는 체크) 결과가 비슷합니다. 저는 DNA 문자열을 색칠하는 또 다른 방법이기 때문에 답을 뽑았습니다. 불행히도 문제를 해결하지 못합니다. – VYT

+0

더 자세히 살펴보면 속성이 지정된 문자열을 만드는 속도가 매우 빠릅니다 (100k 문자열의 경우 1 초 미만). 느린 'NSTextView'를 배치하고 있습니다. 나는'NSTextView'에 대해 더 깊은 잠수를하고 작업 후 나의 대답을 업데이트 할 것입니다. –

+0

다시 한번 감사드립니다! 귀하의 답변을 해결책으로 받아들이고 귀하의 코드를 내 앱에 적용 할 것입니다. – VYT

-1

속성 대신 ciColor을 사용해 보셨습니까? ciColors은 텍스트, 이미지 및 배경과 함께 사용할 수 있습니다.

이 같은 시도 할 수 있습니다 :

txtField.textColor?.ciColor.red 
+0

NSTextView에서 ciColor를 사용하는 방법을 찾을 수 없습니다. 내가 가지고있는 것은 - "CICilter, CIContext 및 CIImage와 같은 다른 Core Image 클래스와 함께 CIColor 객체를 사용합니다." – VYT