Open5
SwiftUI URL部分がリンク化するテキスト (ネタバレOK,名人様歓迎,指摘求む)
iOS 15 から利用可能な AttributedString
を SwiftUI.Text
に与える。
let attributedString = AttributedString(/* ... */)
attributedString[range].link = URL(/* ... */)
で range
部分が SwiftUI.Button
のように表示され、タップするとSafariでページが開かれる。
ユーザ入力の文字列に適用したい場合はRangeが予めわからないので、正規表現を使ってRangeを求める。
もとの String
に StringProtocol.range
を使ってURL部分を抜き出し、
同じ正規表現を使って AttributedString
に対してもう一度 AttributedStringProtocol.range
を使って attributedString[range].link = URL
する。
let inputText: String
let urlPattern: String = "https?://[A-Za-z0-9-._~:/?#\\[\\]@!$&'()*+,;%=]+"
let urls: [URL?] = inputText.matchAll(urlPattern).map { URL(string: String(inputText[$0])) }
var attributedText = AttributedString(inputText)
let ranges: [Range<AttributedString.Index>] = attributedText.matchAll(urlPattern)
for case (let range, let url?) in zip(ranges, urls) {
attributedText[range].link = url
}
こんな感じに作った AttributedString
を
SwiftUI.Text(attributedText)
でOK
StringとAttributedStringそれぞれに1回ずつ同じRegExpを投げてるの気持ち悪いので
AttributedSubStringからStringに変換したいけどわからん
一方で、自前で正規表現マッチせずに NSDataDetector
にURL抽出を移譲する方法がありましたが、こちらは Range<AttributedString.Index>
を作れないかもです