2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Swift で UITextView の URL リンクを短縮表示させる。

Last updated at Posted at 2020-02-26

0.はじめに

Swift で UITextView に表示される URL リンクを短縮表示させたかったので、やってみました。

ついでに、キーワード検索時の強調表示もできる様にしてます。

以下の記事を参考にさせて頂きました。

感謝 ♪♪♪

🙇‍♂️🙇‍♂️🙇‍♂️

1.コード

今回は、UITextView の Extension として、setAttributedText という関数を追加しました。

パラメータの説明は、以下。

  • text: String : [元となるテキスト文字列]
  • shortUrlMaxNum: Int = Int() : [短縮されるURLの最大文字数]
  • keyword: String? = nil : [検索キーワード]
  • keywordBackgroundColor: UIColor = .yellow : [検索キーワードの強調される背景色]
UITextView+Extension.swift
//
//  UITextView+Extension.swift
//

import UIKit

extension UITextView {
    func setAttributedText(text: String, shortUrlMaxNum: Int = Int(), keyword: String? = nil, keywordBackgroundColor: UIColor = .yellow) -> Int {
        var tempText: String = text
        var links: [(url: URL, range: NSRange)] = []
        if shortUrlMaxNum > 0 {
            if let _detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) {
                var truncateCount: Int = 0
                for link in _detector.matches(in: tempText, range: NSMakeRange(0, tempText.utf16.count)) {
                    let startIndex = tempText.utf16.index(tempText.startIndex, offsetBy: (link.range.location - truncateCount))
                    let endIndex = tempText.utf16.index(startIndex, offsetBy: link.range.length)
                    let _tempText = tempText[startIndex..<endIndex]
                    if let _url = link.url, let _ = _url.host, _tempText == _url.absoluteString {
                        var range: NSRange = link.range
                        if _url.absoluteString.count > shortUrlMaxNum {
                            let replacementString: String = _url.absoluteString.prefix(shortUrlMaxNum) + "..."
                            range = NSMakeRange(link.range.location - truncateCount, replacementString.count)
                            tempText.replaceSubrange(
                                Range<String.Index>(NSMakeRange(range.location, link.range.length), in: tempText)!,
                                with: replacementString)
                            truncateCount += (link.range.length - replacementString.count)
                        } else {
                            range = NSMakeRange(link.range.location - truncateCount, _url.absoluteString.count)
                        }
                        links.append((url: _url, range: range))
                    }
                }
            }
        }
        let attrText: NSMutableAttributedString = NSMutableAttributedString(string: tempText, attributes: [
            .font : self.font as Any,
            .foregroundColor : self.textColor as Any,
        ])
        for link in links {
            attrText.addAttribute(.link, value: link.url.absoluteString, range: link.range)
        }
        if let _keyword = keyword {
            if let _regex = try? NSRegularExpression(pattern: _keyword) {
                for match in _regex.matches(in: tempText, range: NSMakeRange(0, tempText.count)) as [NSTextCheckingResult] {
                    attrText.addAttribute(.backgroundColor, value: keywordBackgroundColor, range: match.range)
                }
            }
        }
        self.attributedText = attrText
        return self.attributedText.string.count
    }
}

で、こんな感じに表示されます。

IMG_0152.png


99.ハマりポイント

  • 短縮URL後のテキスト文字列の編集が、結構面倒臭かったですね…。バグってないかちょっと心配…。

  • あと、tempText.utf16 を使っている箇所がありますが、これは絵文字対策で入れたものです。これも、結構面倒臭かった…。

😭😭😭

XX.まとめ

もしかしたら、バグあるかもしれないので、実装する場合は、自己責任でお願いします!

🙇‍♂️🙇‍♂️🙇‍♂️

あと、もっと簡単な方法があれば、教えて頂けるとと嬉しいです!

以上、ご参考になれば ♪♪♪

👋👋👋

2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?