lixiang1994 / AttributedString

基于Swift插值方式优雅的构建富文本, 支持点击长按事件, 支持不同类型过滤, 支持自定义视图等.
MIT License
859 stars 78 forks source link

UILabel.touchesBegan 会发生崩溃:'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds' #29

Closed KennethLaw closed 2 years ago

KennethLaw commented 3 years ago
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard
            isActionEnabled,
            let string = attributed.text,
            let touch = touches.first,
            let (range, action) = matching(touch.location(in: self)) else {
            super.touchesBegan(touches, with: event)
            return
        }
        // 设置触摸范围内容
        touched = (string, range, action)
        // 设置高亮样式
        var temp: [NSAttributedString.Key: Any] = [:]
        action.highlights.forEach { temp.merge($0.attributes, uniquingKeysWith: { $1 }) }
        attributedText = string.value.reset(range: range) { (attributes) in
            attributes.merge(temp, uniquingKeysWith: { $1 })
        }
    }

其中这里会发生崩溃:'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'

        attributedText = string.value.reset(range: range) { (attributes) in
            attributes.merge(temp, uniquingKeysWith: { $1 })
        }

image

image

lixiang1994 commented 3 years ago

方便发一下相关代码吗? 我好复现一下

KennethLaw commented 3 years ago
let SAMPLE = "如有问题,请查看**##**"

struct AttributedConfig {
    var replace: String
    var href: String
    var color: String
}

class AttributedUtils {

    static let TARGET_REPLACE_TAG = "**##**"

    static let DEFAULT_CLICKABLE_COLOR = "#1b97f3"

    static func parse(_ label: UILabel, content: String, hrefs: [AttributedConfig]) {
        var index = 0
        var tempContent = content
        if (content.contains(TARGET_REPLACE_TAG)) {
            for item in hrefs {
                tempContent = tempContent.stringByReplacingFirstOccurrenceOfString(target: TARGET_REPLACE_TAG, withString: item.replace)
                index = index + 1
            }
        }

        if index == 0 {
            label.text = tempContent
            return
        }

        let click: (AttributedString.Action.Result) -> Void = { (result) in

            switch result.content {
            case .string(let value):
                print("点击了文本: \n\(value) \nrange: \(result.range)")
            case .attachment(let value):
                print("点击了附件: \n\(value) \nrange: \(result.range)")
            }
        }

        var normal: AttributedString = "\(tempContent)"
        for item in hrefs {
            guard let range = tempContent.range(of: item.replace) else {
                continue
            }

            let nsRange = NSRange(range, in: tempContent)

            if !item.href.isEmpty {
                normal.add(attributes: [.action(click), .underline(.single, color: UIColor(hexString: DEFAULT_CLICKABLE_COLOR)!)], range: nsRange)
            }

            let color = item.color.isEmpty ? DEFAULT_CLICKABLE_COLOR : item.color
            if let targetColor = UIColor(hexString: color) {
                normal.add(attributes: [.foreground(targetColor)], range: nsRange)
            }
        }

        label.attributed.text = normal
    }
}

调用的地方:UITableViewCell

sample:

let config = AttributedConfig(replace: "官方帮助", href: "www.github.com", color: "#1b97f3")
AttributedUtils.parse(UITableViewCell.titleLabel, content: SAMPLE, hrefs: [config])
lixiang1994 commented 3 years ago

emmm... 我在Demo运行了你这段代码, 似乎没有发现什么问题, 你是稳定复现吗?

KennethLaw commented 3 years ago

线上的崩溃日志收集,目前还不是必现,数量不多; 目前崩溃的系统都是:iOS 14.4.2 先持续关注