解放区在住氷翠 緑の閃光
【解放区在住氷翠】氷翠のお気楽日記

選択範囲の文字に装飾したい

2018-04-16

まずは、出来上がりのフォームはこちら

TextViewで編集することを想定しているので、NSTextViewを使ったやり方になります。

文字の装飾といっても、文字の色を変更するとか、そういうのではないのですが、選択した文字の前後にHTMLのタグを入れたいというのが、今回の目的となります。

ボタンをクリックしたらそうなる。
なので、今回のコードはそのボタンの関数の中身だけをやってみます。

ということで、早速コードです。

// 選択開始
let location = tv.selectedRange().location
if location == -1 { // 選択開始位置が−1なら何もしないで終了
    return
}
// 選択範囲
let length = tv.selectedRange().length
if length == 0 { // 選択範囲が0なら何もしないで終了
    return
}
let length2 = location + (length - 1)
let selectedString = (tv.textStorage as! NSTextStorage).string
// 選択されている部分を取り出す
let text = selectedString.substring(location...length2)
// 選択範囲より前の部分を取り出す
let before = selectedString.substring(0...(location - 1))
// 選択範囲より後ろを取り出す
let after = selectedString.substring((length2 + 1)...)
// 前に付けるタグ
let beforeTag = "<strong>"
// 後ろに付けるタグ
let afterTag = "</strong>"
// 文章を作成する
let answer = before + beforeTag + text + afterTag + after
tv.textStorage?.setAttributedString(NSAttributedString(string: String(answer)))

まず、選択されている文字列の位置関係を明確にしないといけません。

「tv」という変数は「NSTextView」の変数としています。

ということで、「tv.selectedRange().location」で選択開始位置を取得しています。
その次の行で、開始位置が-1なら何もしないで終了させるようにしています。

次に選択範囲として何文字選択されているのか、「tv.selectedRange().length」で取得します。
これは選択開始位置から何文字なのか?というものなので、最初から数えてどこまでなのかというわけではありません。
その次の行ではその範囲の文字数が0なら何もせずに終了としています。

それ以降は文字を取り出す処理をしています。
最初から選択範囲が始まる位置まで、選択範囲が始まる位置から終わる位置まで、選択範囲が終わった位置から後ろまでと、細かく分割しています。

ちなみに、「substring」という関数は拡張しています。

extension String {
    
    func substring(_ r: CountableRange<Int>) -> String {
        
        let length = self.count
        let fromIndex = (r.startIndex > 0) ? self.index(self.startIndex, offsetBy: r.startIndex) : self.startIndex
        let toIndex = (length > r.endIndex) ? self.index(self.startIndex, offsetBy: r.endIndex) : self.endIndex
        
        if fromIndex >= self.startIndex && toIndex <= self.endIndex {
            return String(self[fromIndex..<toIndex])
        }
        
        return String(self)
    }
    
    func substring(_ r: CountableClosedRange<Int>) -> String {
        
        let from = r.lowerBound
        let to = r.upperBound
        
        return self.substring(from..<(to+1))
    }
    
    func substring(_ r: CountablePartialRangeFrom<Int>) -> String {
        
        let from = r.lowerBound
        let to = self.count
        
        return self.substring(from..<to)
    }
    
    func substring(_ r: PartialRangeThrough<Int>) -> String {
        
        let from = 0
        let to = r.upperBound
        
        return self.substring(from..<to)
    }
}

これは拾いものです。
ちょうどいいプログラムがあったので、拝借しました。
使わせて頂きます。

実際に実行してみます。
で、とりあえず、文字を適当に入力します。
文字を選択して、ボタンをクリックします。すると、その選択範囲の前後にタグがついたことを確認できます。

コメントを残す

メールアドレスが公開されることはありません。