[Swift] UITextView を使って、rtf や rtfd を表示する
UITexiViewを使うと、リッチテキスト(RTFファイル、画像付きだとRTFD)を表示することが来ますが、変更履歴、使い方 など、いくつかの長文を表示したいケースがあると思います。
そこで、表示したい文書ファイルを引数にして内容を表示するようにしてみました。
引数で受け取った情報は、クラス内に保持しておきます。
次に、UITextViewを定義します。
今回はUITexiViewしか配置しないため、ViewController内にベタ書きしましたが、凝ったレイアウトにしたり、レイアウトを差し替えたりする場合は、View用のファイルを作成して、外に切り出しても良いと思います。
attributedText にセットするデータは、getAttributeString() を作成して、こちらで取得しています。
getAttributeString() では、初期化時に引数で受け取ったURL、文書タイプからデータを取得しています。
最後にレイアウトを定義します。
上記のサンプルでは、NavigationContoller と TabBarItem の使用を想定して、サイズを定義しています。

TextViewController を初期化する際に、タイトル、URL、文書タイプを指定します。
Bundle.main.url で、ファイル名:Help、拡張子:rtfd のURL(ファイル場所)を取得してます。
URLが取得できた場合のみ、ViewControllerに遷移(表示)するようにしてます。
URL、文書タイプを引数にすることで、自由度を向上させています。
そこで、表示したい文書ファイルを引数にして内容を表示するようにしてみました。
ViewControllerの作成
初期化時にタイトル、文書ファイルのURL、文書の種類を引数で受け取ります。import UIKit
class TextViewController : UIViewController {
    let txvAbout         = UITextView()
    var viewTitle:String = ""
    var url:URL!
    var docType:NSAttributedString.DocumentType!
    
    init(title:String, url: URL, docType: NSAttributedString.DocumentType) {
        super.init(nibName: nil, bundle: nil)
        self.viewTitle = title
        self.url       = url
        self.docType   = docType
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
引数で受け取った情報は、クラス内に保持しておきます。
次に、UITextViewを定義します。
今回はUITexiViewしか配置しないため、ViewController内にベタ書きしましたが、凝ったレイアウトにしたり、レイアウトを差し替えたりする場合は、View用のファイルを作成して、外に切り出しても良いと思います。
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.navigationItem.title        = viewTitle
        
        let view = UIView(frame: self.view.bounds)
        view.backgroundColor  = UIColor.white
        txvAbout.attributedText = getAttributeString()
        txvAbout.isEditable     = false
        view.addSubview(txvAbout)
        
        view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.view.addSubview(view)
    }
    func getAttributeString() -> NSAttributedString {
        if (self.url != nil) {
            let attributeOptions : [NSAttributedString.DocumentReadingOptionKey : Any] = [.documentType: self.docType]
            let attributeString = try! NSAttributedString(url: self.url,
                                                          options: attributeOptions,
                                                          documentAttributes: nil)
            return attributeString
        } else {
            return NSAttributedString()
        }
    }
attributedText にセットするデータは、getAttributeString() を作成して、こちらで取得しています。
getAttributeString() では、初期化時に引数で受け取ったURL、文書タイプからデータを取得しています。
最後にレイアウトを定義します。
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let topMergin = UIApplication.shared.statusBarFrame.height
            + (self.navigationController?.navigationBar.frame.height)!
        let footerMergin = (self.tabBarController?.tabBar.frame.height)!
        var y:CGFloat
        var pos: CGPoint, sz: CGSize
        
        //
        y = topMergin
        pos = CGPoint(x: 0, y: y )
        sz  = CGSize(width: view.bounds.width,
                     height: view.bounds.height - topMergin - footerMergin )
        txvAbout.frame = CGRect(origin: pos, size: sz)
        
    }
上記のサンプルでは、NavigationContoller と TabBarItem の使用を想定して、サイズを定義しています。
使い方
プロジェクト内に Help.rtfd を作成してます。
TextViewController を初期化する際に、タイトル、URL、文書タイプを指定します。
    let title = NSLocalizedString("title-HelpView",comment: "")
    if let url = Bundle.main.url(forResource: "Help", withExtension: "rtfd"){
        let help = TextViewController(title: title,
                                      url: url,
                                      docType: NSAttributedString.DocumentType.rtfd)
        self.navigationController!.pushViewController(help, animated: true)
    }
Bundle.main.url で、ファイル名:Help、拡張子:rtfd のURL(ファイル場所)を取得してます。
URLが取得できた場合のみ、ViewControllerに遷移(表示)するようにしてます。
URL、文書タイプを引数にすることで、自由度を向上させています。
最後に
共通的な部品を作成しておくことで、コードの冗長性を抑えることが出来そうです。
他にもっと良い方法があるかもしれませんので、改良・調整を加えていこうと思います。
コメント
コメントを投稿