NSAttributedString 初始化抛出 NSRangeException
NSAttributedString initialization throws NSRangeException
我写了一个简单的扩展来解码 html 个实体:
extension String {
func htmlDecode() -> String {
if let encodedData = self.data(using: String.Encoding.unicode) {
let attributedString = try! NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode], documentAttributes: nil)
return attributedString.string
}
return self
}
}
现在它在 if let attributedString …
:
行抛出错误
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 2]'
并且 self
不是 nil 之类的,只是像这样的 String
:
self = (String) "...über 25'000 Franken..."
这个奇怪的NSArray
异常是从哪里来的?
似乎是一个错误,可能与 Swift 字符串处理字符的方式与 NSString
不同。
我会提交雷达。
我只是 运行 用另一个错误来解决这个错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance 0x60000024b790'
并且在这段代码中发现了一个严重的错误:
我正在将 String.Encoding.unicode
- 一个 Swift 值 - 传递给一个 Objective-C 导致应用程序崩溃的方法。使用 String.Encoding.unicode.rawValue
后,崩溃消失了:
extension String {
func htmlDecode() -> String {
if let encodedData = self.data(using: String.Encoding.unicode) {
if let attributedString = try? NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode.rawValue], documentAttributes: nil) {
return attributedString.string
}
}
return self
}
}
瞎猜:你确定初始化发生在主线程上吗?
我遇到了完全相同的问题。我注意到在我的例子中,异常发生在可重现的条件下(UICollectionViewController 中的动画),但我无法找到真正的原因。我最好的猜测是它是一个框架错误,所以我也建议你提交雷达。
我最终将我的 HTML 格式化字符串在它工作时预渲染到缓存(又名数组)中,然后根据需要从中加载 NSAttributedStrings。
请注意,此解决方案可能不适合您的用例,因为我一次只需要处理有限数量的格式化字符串,因此知道提前呈现它们的费用。
在我的例子中,发生这种情况是因为我试图从处于分离状态的 UICollectionViewCell
中实例化一个 NSAttributedString
(在它被插入父 UICollectionView 之前)。
DispatchQueue.main.async { let text = yourHtmlText.htmlDecode() }
我写了一个简单的扩展来解码 html 个实体:
extension String {
func htmlDecode() -> String {
if let encodedData = self.data(using: String.Encoding.unicode) {
let attributedString = try! NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode], documentAttributes: nil)
return attributedString.string
}
return self
}
}
现在它在 if let attributedString …
:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 2]'
并且 self
不是 nil 之类的,只是像这样的 String
:
self = (String) "...über 25'000 Franken..."
这个奇怪的NSArray
异常是从哪里来的?
似乎是一个错误,可能与 Swift 字符串处理字符的方式与 NSString
不同。
我会提交雷达。
我只是 运行 用另一个错误来解决这个错误:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue unsignedIntegerValue]: unrecognized selector sent to instance 0x60000024b790'
并且在这段代码中发现了一个严重的错误:
我正在将 String.Encoding.unicode
- 一个 Swift 值 - 传递给一个 Objective-C 导致应用程序崩溃的方法。使用 String.Encoding.unicode.rawValue
后,崩溃消失了:
extension String {
func htmlDecode() -> String {
if let encodedData = self.data(using: String.Encoding.unicode) {
if let attributedString = try? NSAttributedString(data: encodedData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.unicode.rawValue], documentAttributes: nil) {
return attributedString.string
}
}
return self
}
}
瞎猜:你确定初始化发生在主线程上吗?
我遇到了完全相同的问题。我注意到在我的例子中,异常发生在可重现的条件下(UICollectionViewController 中的动画),但我无法找到真正的原因。我最好的猜测是它是一个框架错误,所以我也建议你提交雷达。
我最终将我的 HTML 格式化字符串在它工作时预渲染到缓存(又名数组)中,然后根据需要从中加载 NSAttributedStrings。
请注意,此解决方案可能不适合您的用例,因为我一次只需要处理有限数量的格式化字符串,因此知道提前呈现它们的费用。
在我的例子中,发生这种情况是因为我试图从处于分离状态的 UICollectionViewCell
中实例化一个 NSAttributedString
(在它被插入父 UICollectionView 之前)。
DispatchQueue.main.async { let text = yourHtmlText.htmlDecode() }