Day: May 16, 2018

Swift4:文字列に色付(ソースコード)

UITextViewの任意の文字列をユーザーが選択し、色をつけることができる機能を実装しました。ソースコードはここ

文字数の問題:

最初、UITextViewの.textを選択された文字列、その前の文字列、その後の文字列に分けて抽出し、NSMutableAttributedStringで色付けしたものと合成する方法で実装を進めました。しかし、この方法だと、yUserNote.selectedRangeで入ってくる選択範囲に絵文字が含まれると、文字数ではなく、バイト数で入ってくることがわかりました(参考:文字列の長さを取得)。ソースコードの最後にあるCallGetStringByNSRangeを参考にしてください。

  • 重要:文字列に2バイトコードが含まれる場合、pString.utf16.count のような表現にしないと、yUserNote.attributedTextと生合成が保てない。

文字属性の設定の仕方:

そこで、抽出合成方法を放棄し、次の通り、UITextViewをNSMutableAttributedStringでUILabelに取り出し、選択文字列だけを色付けし、UILabelからUITextViewに戻す実装にしました。wAtt = yUserNote.attributedText as! NSMutableAttributedStringとすると、Xcodeのバグと思われるのですが、この命令で以上してしまうため、その迂回作としてUILabel➡︎UITextViewとしました。

  • 重要:UITextViewは直接NSMutableAttributedStringをハンドリングできないが、UILabelを仲介すれば、うまくいく。

import UIKit                                                        //
import WebKit                                                       //
class MesaNote: UIViewController, WKNavigationDelegate, WKUIDelegate {//
    @IBOutlet weak var  yUserNote:UITextView!                       //Note area
    var wRangeOrg:NSRange               = NSRange()                 //
    var wAtt:NSMutableAttributedString  = NSMutableAttributedString()//
    var wLabel:UILabel                  = UILabel()                 //
    override func viewDidLoad() {                                   //
        super.viewDidLoad()                                         //
        let wkString2:String        = “012345678900️⃣1️⃣abcde”        //
        yUserNote.attributedText    = NSAttributedString(string: wkString2,//
          attributes:[.foregroundColor :UIColor.blue, .font :UIFont(name: “Arial-BoldMT”, size:15)!])//
    }//============================================================//

    @IBAction func ExecIBAColor(){                                  //<*Add color to the selected text*>
        wRangeOrg                   = yUserNote.selectedRange       //
        wLabel.attributedText       = yUserNote.attributedText      //
        wAtt                        = wLabel.attributedText as! NSMutableAttributedString//
        wAtt.addAttributes([.foregroundColor : UIColor.red], range: wRangeOrg)//
        yUserNote.attributedText    = wAtt
    }//============================================================//

    override func didReceiveMemoryWarning() {                       //
        super.didReceiveMemoryWarning()                             //
        // Dispose of any resources that can be recreated.          //
    }//=============================================================//

 func CallGetStringByNSRange(_ pString:String, pRange:NSRange) -> String {//<*NSRange指定範囲の文字列を抽出する*>
        if pRange.location >= pString.utf16.count || pRange.location < 0
           || pRange.length <= 0 || pRange.location+pRange.length > pString.utf16.count { return “” }
        return String(pString[Range(pRange, in: pString)!])         //
    }//=============================================================//
}

Screenshot 2018-05-16 23.59.29