HTMLライクなデザインでテキストにハイパーリンクを付けることになりました。
各項目を入力して送信ボタンを押してください。何か分からないことがありましたら、こちらからお問い合わせください。
こんなケースですね。アンダーバーだけハイパーリンク化しないといけなかったんですね。これをUILabelを使って実現できるか色々調べて試してみました。
NSMutableAttributedStringを使う
NSMutableAttributedStringというクラスがあって、Stringに様々な属性を付加することができます。UILabelやUITextViewにはatributedTextというプロパティがあるので、このプロパティにNSMutableAttributedStringインスタンスをセットするとアンダーラインや文字色など変化あるテキストを表示することができます。WindowsやAndroidだとマークアップ言語に記述できるのですが、iOSだとコードビハインドで遅れていますね。まあ、しょうがないです。
let textView = UITextView() textView.isSelectable = true textView.isEditable = false let text = "各項目を入力して送信ボタンを押してください。何か分からないことがありましたら、こちらからお問い合わせください。" let attributedString = NSMutableAttributedString(string: text) let range = NSString(string: text).range(of: "こちらからお問い合わせください") attributedString.addAttribute(NSAttributedStringKey.link, value: "https://www.yahoo.co.jp/", range: range) attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value: 1, range: range) textView.attributedText = attributedString
これで「こちらからお問い合わせください」だけハイパーリンク化されます。しかしこれはUITextViewを使った場合です。
UILabelのテキストをハイパーリンク化したい
実現できたとはいえ、たかがリンク付きのテキストを貼るためにUITextViewは大袈裟だと思うんです。シンプルにUILabelを使いたいですよね。そもそもUILabelにもattributedTextプロパティがあるのだから、下記のように書けば動くのではないかと思いますよね。
let label = UILabel() let text = "各項目を入力して送信ボタンを押してください。何か分からないことがありましたら、こちらからお問い合わせください。" let attributedString = NSMutableAttributedString(string: text) let range = NSString(string: text).range(of: "こちらからお問い合わせください") attributedString.addAttribute(NSAttributedStringKey.link, value: "https://www.yahoo.co.jp/", range: range) attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value: 1, range: range) label.attributedText = attributedString
残念ながら動かないんですよね。
なぜUILabelではハイパーリンク化できないのか
実はUITextViewでもプロパティを変更するとUILabelと同様にハイパーリンクが動かなくなります。それがisSelectableプロパティです。最初のコードを下記のように書き換えるとハイパーリンクは動きません。
let textView = UITextView() // textView.isSelectable = true textView.isSelectable = false textView.isEditable = false let text = "各項目を入力して送信ボタンを押してください。何か分からないことがありましたら、こちらからお問い合わせください。" let attributedString = NSMutableAttributedString(string: text) let range = NSString(string: text).range(of: "こちらからお問い合わせください") attributedString.addAttribute(NSAttributedStringKey.link, value: "https://www.yahoo.co.jp/", range: range) attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value: 1, range: range) textView.attributedText = attributedString
選択できないからハイパーリンクのタップにも反応しないってことなんでしょうか…。そしてUILabelにはisSelectableプロパティがありません。選択不可能なUIコンポーネントなんですよね…。このためUILableではハイパーリンク化ができないというわけです。
どうしてもUILabelをハイパーリンク化したいなら
UILabelにUITapGestureRecognizerを設定してタップイベントを作ってそこでリンク処理を実装すればできるようです。
qiita.com
「これだけ」で実現できますって書いてありますが、WindowsやAndroidでマークアップ言語で済ませているのに慣れていると、たった1つのハイパーリンクにこんなにコード書かないといけないXcodeとSwiftに軽く絶望してしまいますね…。