LoginSignup
3
2

More than 1 year has passed since last update.

UITextViewの文字を複数リンク化させる方法

Last updated at Posted at 2020-05-21

はじめに

スクリーンショット 2020-05-21 19.19.21.png

iOSが意外に苦手なリンク化
HTMLみたいにタグで囲った範囲をリンク化する!みたいに出来たら便利なのですが、出来ないので

リンク化したい文字列の場所とタップした位置でゲームみたいに当たり判定でリンクをタップしたか判定します!

ViewController + Storyboardで解説

Storyboard(Xibでも可)にUITextViewを貼り付ける

スクリーンショット 2020-05-21 16.35.01.png

制約も適当に張ります。
スクリーンショット 2020-05-21 16.35.15.png

UITextViewにTapGestureを張ります!
スクリーンショット 2020-05-21 18.34.26.png

スクリーンショット 2020-05-21 18.35.34.png

こんな感じ!

スクリーンショット 2020-05-21 18.38.35.png

Storyboardとコードをつなげる

Controlキーを押しながら、TextViewをひっぱりコードに張りますー
(ちなみにエディタを分割して開くには、ファイルをoptionキーを押しながらクリックします)

スクリーンショット 2020-05-21 16.38.20.png

TapGestureもコードにつなげておきます〜

スクリーンショット 2020-05-21 18.43.36.png

以下のようになりました!

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var messageTextView: UITextView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    @IBAction func didTapMessageView(_ sender: UITapGestureRecognizer) {
    }
}

本題

messageTextViewの初期設定をしてあげます

仕様にもよりますが、以下の制御があったほうが理想だと思います。

messageTextView.isUserInteractionEnabled = true
messageTextView.isEditable = false
messageTextView.isSelectable = false
messageTextView.isScrollEnabled = false
   @IBOutlet weak var messageTextView: UITextView! {
        didSet {
            messageTextView.isUserInteractionEnabled = true
            messageTextView.isEditable = false
            messageTextView.isSelectable = false
            messageTextView.isScrollEnabled = false
            let mutableAttributedString = NSMutableAttributedString()
            let normalAttributes: [NSAttributedString.Key: Any] = [
                .foregroundColor: UIColor.gray,
                .font: UIFont.monospacedSystemFont(ofSize: 18, weight: .medium)
            ]
            let linkAttributes:  [NSAttributedString.Key: Any] = [
                .foregroundColor: UIColor.link,
                .underlineStyle: NSUnderlineStyle.single.rawValue,
                .font: UIFont.monospacedSystemFont(ofSize: 22, weight: .medium)
            ]

            mutableAttributedString.append(
                NSAttributedString(
                    string: "吾輩わがはいは猫である。",
                    attributes: normalAttributes
                )
            )
            mutableAttributedString.append(
                NSAttributedString(
                    string: "名前",
                    attributes: linkAttributes
                )
            )
            mutableAttributedString.append(
                NSAttributedString(
                    string: "はまだ無い。",
                    attributes: normalAttributes
                )
            )
            mutableAttributedString.append(
                NSAttributedString(
                    string: "どこで",
                    attributes: linkAttributes
                )
            )
            mutableAttributedString.append(
                NSAttributedString(
                    string: "生れたかとんと見当けんとうがつかぬ。",
                    attributes: normalAttributes
                )
            )
            messageTextView.attributedText = mutableAttributedString
        }
    }

次にタップ時の挙動を記述していきます。

    @IBAction func didTapMessageView(_ sender: UITapGestureRecognizer) {
        guard let text = messageTextView.text else { return }
        let name = "名前"
        let pos = "どこで"
        
        let nameRange = (text as NSString).range(of: name)
        let posRange = (text as NSString).range(of: pos)
        
        let location = sender.location(in: messageTextView)
        let textPosition = messageTextView.closestPosition(to: location)
        let tapPosition = messageTextView.offset(from: messageTextView.beginningOfDocument, to: textPosition!)
        
        if NSLocationInRange(tapPosition, nameRange) {
            print("たま")
        }
        
        if NSLocationInRange(tapPosition, posRange) {
            print("縁側")
        }
    }

結果

3j0z2-rnaio.gif

終わり

ポイントはNSLocationInRangeで毎回当たり判定的なものを行なって毎回処理を走らせるところです!

これをUIViewControllerRepresentableすればSwiftUIでも行けるのかも?
今度試してみます!

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2