Swift 4.0富文本属性下标报错:无法用String访问NSAttributedStringKey字典
解决Swift 4中NSAttributedString属性下标访问的错误
这个错误是Swift 4对NSAttributedString的属性系统做了类型安全升级导致的——原来Swift 3里用字符串作为属性键,Swift 4开始统一使用NSAttributedStringKey类型来管理这些键,所以直接用字符串下标访问[NSAttributedStringKey : Any]类型的字典就会报错。
针对你的YYKit富文本点击场景,有两种修复方式:
方式一:直接使用NSAttributedStringKey(rawValue:)转换
把原来的字符串键转换成NSAttributedStringKey实例,修改后的代码如下:
entemessageText.highlightTapAction = { (containerView: UIView, text: NSAttributedString, range: NSRange, rect: CGRect) -> () in let attributes = text.attributes(at: range.location, effectiveRange: nil) // 将字符串键转为NSAttributedStringKey if let attrs = attributes[NSAttributedStringKey(rawValue: "YYTextHighlight")] as? YYTextHighlight { if let url = attrs.userInfo?["url"] as? String { // 这里建议用可选绑定代替强制解包,避免崩溃 if let urlObj = URL(string: url) { self.openUrl(urlObj) } } } }
方式二:扩展NSAttributedStringKey封装自定义键(更规范)
为了代码更易读和维护,推荐给NSAttributedStringKey加一个扩展,把YYText的自定义键封装成静态属性:
extension NSAttributedStringKey { static let yyTextHighlight = NSAttributedStringKey(rawValue: "YYTextHighlight") }
然后在代码里直接使用这个静态属性:
entemessageText.highlightTapAction = { (containerView: UIView, text: NSAttributedString, range: NSRange, rect: CGRect) -> () in let attributes = text.attributes(at: range.location, effectiveRange: nil) if let attrs = attributes[.yyTextHighlight] as? YYTextHighlight { if let url = attrs.userInfo?["url"] as? String, let urlObj = URL(string: url) { self.openUrl(urlObj) } } }
另外补充一个小建议:代码里的attrs.userInfo!和URL(string: url)!都是强制解包,一旦对应的value不存在或者url格式错误,会直接导致崩溃,所以改成可选绑定更安全,我在上面的代码里已经做了调整。
内容的提问来源于stack exchange,提问作者guru
相关产品推荐
相关产品推荐

