问题描述
我正在尝试使用文本中的多个链接设置 UITextView。我的实现基于 here 描述的建议。大多数链接都按预期工作,但是点击其中一些链接会使应用崩溃,并显示以下错误 EXC_BREAKPOINT (code=1,subcode=0x185646694)
:
Crash error
Call stack
我的 UITextView 配置代码:
private var actionableLinks = [(String,()->Void)]() // each link = (actionableString,tapAction)
private func setupMessageText() {
guard messageTextView != nil else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.paragraphSpacingBefore = 16
let attributedText = NSMutableAttributedString(string: messageText,attributes: [
.font: messageTextView.font!,.foregroundColor: messageTextView.textColor!,.paragraphStyle: paragraphStyle
])
addActionableLinks(to: attributedText)
messageTextView?.attributedText = attributedText
}
private func addActionableLinks(to attributedText: NSMutableAttributedString) {
actionableLinks.forEach {
let actionableString = $0.0
if let nsRange = messageText.nsRange(of: actionableString) {
attributedText.addAttribute(.link,value: actionableString,range: nsRange)
}
}
}
为了处理点击动作,我实现了正确的 UITextViewDelegate 方法:
func textView(_ textView: UITextView,shouldInteractWith URL: URL,in characterRange: NSRange,interaction: UITextItemInteraction) -> Bool {
let tappedLinkString = URL.absoluteString
if let link = actionableLinks.first(where: { $0.0 == tappedLinkString }) {
let tapAction = link.1
tapAction()
return false
}
return true
}
我为此屏幕的故事板配置(我在故事板中设置了 UITextView 委托):
Storyboard Configuration
任何见解将不胜感激!谢谢。
解决方法
问题已解决!感谢 Larme 提供的快速见解和资源。
这确实是一个尝试在 UITextView 中使用错误字符串作为链接的情况,该链接在内部被转换为 URL。由于这是一个包含空格的字符串,Apple 内部转换为 URL 失败。
我的字符串“support”链接正确并且工作正常,但另一个字符串“新条款和条件”失败。
解决办法
为了解决这个问题,我在将链接属性添加到 UITextView 的属性文本时使用了百分比编码。
private func addActionableLinks(to attributedText: NSMutableAttributedString) {
actionableLinks.forEach {
let actionableString = $0.0
if let nsRange = messageText.nsRange(of: actionableString) {
let escapedActionableString = escapedString(actionableString)
attributedText.addAttribute(.link,value: escapedActionableString,range: nsRange)
}
}
}
private func escapedString(_ string: String) -> String {
return string.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? string
}
我还更改了委托方法以检查是否与转义字符串匹配:
func textView(_ textView: UITextView,shouldInteractWith URL: URL,in characterRange: NSRange,interaction: UITextItemInteraction) -> Bool {
let tappedLinkString = URL.absoluteString
for (actionableString,tapAction) in actionableLinks {
let escapedActionableString = escapedString(actionableString)
if escapedActionableString == tappedLinkString {
tapAction()
return false
}
}
return true
}
谢谢!