UITextview为整个属性文本着色,而不是给定范围

我需要更改链接文本的颜色并使其可点击。 我从UITextView创建了一个简单的子类。首先,一切似乎都运行良好。但是,当我需要多次更改文本时,它将整个文本显示为蓝色,而不仅仅是链接范围。

我在此处添加游乐场代码。如果在“ TAP TAP”上点击3次,您将明白我的意思。

    import UIKit
    import PlaygroundSupport

    final class TextViewWithLinks: UITextView {
        typealias LinkParameters = [(displayText: String,urlPath: String)]

        override public var text: String! {
            get { attributedText.string }
            set { setupText(newValue) }
        }

        var linkParameters: LinkParameters = [] {
            didSet { setupText(text) }
        }

        init() {
            super.init(frame: .zero,textContainer: nil)
            setup()
        }

        @available(*,unavailable)
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

        private func setup() {
            backgroundColor = nil
            textColor = .gray
            textAlignment = .center
            isSelectable = true
            isEditable = false
            isScrollEnabled = false
            delegate = self
        }

        private func setupText(_ text: String) {
            let newAttributedText = NSMutableAttributedString(string: text)

            let textColor = self.textColor ?? .gray
            let font = self.font ?? .systemFont(ofSize: 14)
            let paragraph = NSMutableParagraphStyle()
            paragraph.alignment = textAlignment
            newAttributedText.addAttributes(
                [.font: font,.foregroundColor: textColor,.paragraphStyle: paragraph],range: NSRange(location: 0,length: text.count)
            )

            for linkParameter in linkParameters {
                let url = URL(string: linkParameter.urlPath)
                let displayText = linkParameter.displayText.lowercased()
                newAttributedText.addAttributes(
                    [.link: url ?? linkParameter.urlPath,.foregroundColor: UIColor.blue],range: (text.lowercased() as NSString).range(of: displayText)
                )
            }

            self.attributedText = newAttributedText
        }
    }

    extension TextViewWithLinks: UITextViewDelegate {
        func textView(
            _ textView: UITextView,shouldInteractWith URL: URL,in characterRange: NSRange,interaction: UITextItemInteraction) -> Bool {
            return true
        }
    }


    class MyViewController: UIViewController {
        private let button = UIButton()
        private let textView = TextViewWithLinks()

        override func loadView() {
            super.loadView()
            let view = UIView()
            view.backgroundColor = .white

            textView.text = "My text with a link"
            textView.linkParameters = [
                (displayText: "link",urlPath: "https://www.google.com/")
            ]

            button.setTitle("TAP TAP",for: .normal)
            button.setTitleColor(.black,for: .normal)
            button.addTarget(self,action: #selector(tappedButton),for: .touchUpInside)

            self.view = view
            layoutTextView()
            layoutButton()
        }

        @objc private func tappedButton() {
            textView.text = "\nNew line" + textView.text
        }

        private func layoutTextView() {
            view.addSubview(textView)
            textView.translatesAutoresizingMaskintoConstraints = false
            NSLayoutConstraint.activate([
                textView.topAnchor.constraint(equalTo: view.topAnchor,constant: 50),textView.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant: 20),textView.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant: -20)
            ])
        }

        private func layoutButton() {
            view.addSubview(button)
            button.translatesAutoresizingMaskintoConstraints = false
            NSLayoutConstraint.activate([
                button.topAnchor.constraint(equalTo: view.topAnchor,constant: 5),button.heightAnchor.constraint(equalToConstant: 30),button.widthAnchor.constraint(equalToConstant: 100),button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
            ])
        }
    }
    // Present the view controller in the Live View window
    PlaygroundPage.current.liveView = MyViewController()

唯一的解决方案是,我发现删除.foregroundColor: UIColor.blue并仅为链接属性添加.link: url ?? linkParameter.urlPath。 但另一方面,如果我只需要将其着色为蓝色,则该行为将再次失败。

有什么主意吗?

l13952781422 回答:UITextview为整个属性文本着色,而不是给定范围

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3160157.html

大家都在问