【Swift5】UITextViewの任意の文字列をタップ可能なリンクにする

検証環境:
Xcode 11.3
Swift 5.1.3

UITextView の任意の文字列のタップ可能なリンクにする方法についてです。

f:id:xyk:20200130122003p:plain

リンク化する文字列のみ、色を変えてアンダーラインを追加します。
UITextView のサブクラスして実装し、IBDesignable と IBInspectable を使って Storyboard から設定できるようにしました。
UITextView の text プロパティに全文を設定し、リンク化したい部分を linkText に設定します。

import UIKit

@IBDesignable
class LinkTextView: UITextView, UITextViewDelegate {
    
    @IBInspectable
    var fontSize: CGFloat = 14
    
    @IBInspectable
    var isBold: Bool = false
    
    @IBInspectable
    var linkText: String = ""
    
    @IBInspectable
    var linkColor: UIColor = .red
    
    @IBInspectable
    var linkURL: String = ""

    override func awakeFromNib() {
        super.awakeFromNib()
        configure()
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        configure()
    }
    
    private func configure() {
        
        let systemFont: UIFont = isBold ? .boldSystemFont(ofSize: fontSize) : .systemFont(ofSize: fontSize)
        let attributedString = NSMutableAttributedString(string: text)
        let attrs: [NSAttributedString.Key: Any] =  [
            .font: systemFont,
            .foregroundColor: textColor ?? .black
        ]
        attributedString.setAttributes(attrs, range: NSString(string: text).range(of: text))
        let linkAttrs: [NSAttributedString.Key: Any] =  [
            .font: systemFont,
            .link: linkURL // リンク先URL
        ]
        attributedString.setAttributes(linkAttrs, range: NSString(string: text).range(of: linkText))
        attributedText = attributedString
        linkTextAttributes = [
            .foregroundColor: linkColor, // リンクの色
            .underlineStyle: NSUnderlineStyle.single.rawValue // アンダーラインを追加
        ]
        
        backgroundColor = .clear
        isSelectable = true
        isEditable = false
        isScrollEnabled = false
        delegate = self
    }
    
    // MARK: - UITextViewDelegate
    
    func textView(_ textView: UITextView,
                  shouldInteractWith URL: URL,
                  in characterRange: NSRange,
                  interaction: UITextItemInteraction) -> Bool {
        
        UIApplication.shared.open(URL)
        return false
    }
}

以前の記事

xyk.hatenablog.com