2017-10-11 14 views
2

このコードは、CFAttributedStringがスレッドセーフではないことを示していますか?あるいは私はセットアップで何か間違っていますか?CFAttributedStringスレッドの安全性

私はCFAttributedStringが複数のスレッドから読み込むのは安全だと思っていましたが、数回実行するたびにこのコードにクラッシュが発生しました。

@IBAction func testIt(_ sender: Any?) { 
    let testString = "Hello world! Lets make this a bit longerrrrrrrrrrrrrrrr." as CFString 
    let testStringLength = CFStringGetLength(testString) 

    let testAttributedString = CFAttributedStringCreateMutable(kCFAllocatorDefault, testStringLength) 
    CFAttributedStringReplaceString(testAttributedString, CFRange(location: 0, length: 0), testString) 
    CFAttributedStringEndEditing(testAttributedString) 
    for i in 0..<testStringLength { 
     let range = CFRange(location: i, length: 1) 
     let keyAndValue = "\(i)" as CFString 
     CFAttributedStringSetAttribute(testAttributedString, range, keyAndValue, keyAndValue) 
    } 

    let immutableTestAttributedString = CFAttributedStringCreateCopy(kCFAllocatorDefault, testAttributedString) 
    DispatchQueue.concurrentPerform(iterations: 100) { _ in 
     var index: CFIndex = 0 
     var effectiveRange: CFRange = CFRange(location: 0, length: 0) 
     while index < testStringLength { 
      // Crash happens here EXC_BAD_ACCESS (code=1, address=0x24) 
      let _ = CFAttributedStringGetAttributes(immutableTestAttributedString, index, &effectiveRange) 
      index = effectiveRange.location + effectiveRange.length 
     } 
    } 
} 

答えて

1
let testString = "Hello world! Lets make this a bit longerrrrrrrrrrrrrrrr." as CFString 

これは間接の2層程度であり、あなたとの間であることがまだ動作するかどうかを(ガッツでダウン非常に異なるコードパスを呼び出すかどうかCFString、を装っスウィフト文字列です。 a radar)。

CFStringを正しく作成して、期待どおりに動作するかどうかを確認してください。

var bytes = Array("Hello world! Lets make this a bit longerrrrrrrrrrrrrrrr.".utf16) 
let testString = CFStringCreateWithCharacters(nil, &bytes, bytes.count) 

(もちろん、私は非常にNSAttributedStringなく、CFAttributedStringにこのすべての仕事をしてお勧めします。Swift->財団ブリッジがはるかに簡単であるとSwift->ファンデーション> CoreFoundationのブリッジに比べて常に使用されている。このかもしれませんちょうどそのブリッジにかかわる問題であることが、あなたの世界はまだあなたがそれを避ける場合は非常に簡単になるだろう。)


私は純粋のCFString/wの問題を再現することができていないが、これは間違いなくスレッドセーフではありません。 CoreFoundationはオープンソース(sort-of ...ですが、この目的には十分です)ですので、コードを自分で見ることができます。結局CFAttributedStringGetAttributesは、内部キャッシュを更新したことを中心にロックしない、blockForLocationを呼び出します。私はこれがスレッドセーフであると約束している文書では何も見ていません。

+0

私は文字列をそのように作成すると、残念ながら私はまだ同じ場所にエラーが表示されています。この場合CFAttributedStringを使用する理由は、コード内の場所が高温で、CFAttributedStringSetAttributeの実行速度が非常に速く、NSMutableAttributedStringで属性を追加するためです。 –

+0

素早いブリッジングがどのように機能するかについて、どこで知ることができるでしょうか?特にパフォーマンスの問題を監視する必要があります。私はSwiftのコアテキストを使用して多くの作業をしており、最適化段階に入っています。ありがとう。 –

+0

ありがとうございました。 NSAttributedStringが安全なものとしてリストされ、Core Foundationがここで「一般的に」安全と宣言されて以来、スレッドセーフであることを期待していました:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.htmlしかし、この場合、あなたの助けをもう一度知り、感謝しています。 –

関連する問題