2017-10-11 201 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 

这是斯威夫特的字符串伪装成CFString,这是大约两个间接层和胆量调用一个非常不同的代码路径下(不管是应该能够正常与否是你们之间一个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字符串,这绝对不是线程安全的。 CoreFoundation是开源的(排序......,但足够用于此目的),因此您可以自己查看代码。最后CFAttributedStringGetAttributes调用blockForLocation,它更新内部缓存并且没有锁定。我没有看到任何承诺这是线程安全的文档。

+0

感谢您的提示,不幸的是,当我以这种方式创建字符串时,我仍然在同一个地方看到一个错误。在这种情况下使用CFAttributedString的原因是因为它在代码中是一个热门的地方,CFAttributedStringSetAttribute看起来运行速度快很多,然后用NSMutableAttributedString添加属性。 –

+0

您是否有任何关于如何快速桥接工作的更多信息?尤其要注意性能问题。我在Swift的Core Text上做了很多工作,现在处于优化阶段。谢谢。 –

+0

谢谢,你的帮助。我期待线程安全,因为NSAttributedString被列为安全,并且Core Foundation被广告为“通常”安全:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html但在这种情况下,非常了解并再次感谢您的帮助。 –