1
0

More than 1 year has passed since last update.

HTMLをより自在にStringに変換したい!HTMLテンプレートを使ってみよう

Posted at

はじめに

APIからテキスト情報を受け取り、画面に表示することは本当に日常のようなことだと思いますが、
以下のようにHTML様式で情報を受け取る時はどうすれば良いでしょうか。
簡単な方法からHTMLテンプレートを使ったより柔軟なテキスト変換を調べてみましょう。

"おはようございます。<br>\r\nテストで作ってます<br>蒸し暑いですな。</u>\r\n<br>\r\n<b>助けてください</b><br><br>\r\n\r\n<br><br>\r\n<p style=\"color:red;\">うああああああああ</p><br>"

実用例

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var testLabel: UILabel!
    
    let originText = "おはようございます。<br>\r\nテストで作ってます<br>蒸し暑いですな。</u>\r\n<br>\r\n<b>助けてください</b><br><br>\r\n\r\n<br><br>\r\n<p style=\"color:red;\">うああああああああ</p><br>"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        testLabel.text = originText
    }
}

(originTextはAPIから受け取ってるテキストだと考えてください)
仮に上のようなコードがあると考えてみましょう。このままでビルドすると下のようになります。

一瞬見てもよろしくないですね。このHTMLタグを単純に消すだけではなく、
タグで設定されてるスタイルを適用するには一応Stringをextensionしましょう。

extension String {
    var htmlToAttributedString: NSMutableAttributedString? {
        guard let data = data(using: .utf8) else { return nil }
        do {
            return try NSMutableAttributedString(data: data,
                                                 options: [.documentType: NSMutableAttributedString.DocumentType.html,
                                                           .characterEncoding: String.Encoding.utf8.rawValue],
                                                           documentAttributes: nil)
        } catch {
            return nil
        }
    }
}

// ViewDidLoad
override func viewDidLoad() {
        super.viewDidLoad()
        let attributedText = originText.htmlToAttributedString
        //testLabel.textではなく、attributedTextであることに注意
        testLabel.attributedText = attributedText
    }

上記のようにHTML文が綺麗に変わったことを確認できます。
ですが、まだサイズが小さくて読みにくい問題が残ってます。
これを解決するうちに、黒いテキストの色も青に変えてみましょう。 

override func viewDidLoad() {
        super.viewDidLoad()
        let attributedText = originText.htmlToAttributedString
        //addAttributeで属性を追加
        attributedText?.addAttribute(.font, value: UIFont(name: "HiraginoSans-W3", size: 20)!, range: NSRange(location: 0, length: attributedText?.length ?? 0))
        attributedText?.addAttribute(.foregroundColor, value: UIColor(ciColor: .blue), range: NSRange(location: 0, length: attributedText?.length ?? 0))

        testLabel.attributedText = attributedText
    }

   
こうすると赤文字も青になり、原文HTMLのボルドタグも適用されなくなる問題があります。
私はこれを直すためにHTML Templateを使いました。
実用例を見ましょう。

HTML Templateを使った実用例

class ViewController: UIViewController {
    @IBOutlet weak var testLabel: UILabel!
    
    let originText = "おはようございます。<br>\r\nテストで作ってます<br>蒸し暑いですな。</u>\r\n<br>\r\n<b>助けてください</b><br><br>\r\n\r\n<br><br>\r\n<p style=\"color:red;\">うああああああああ</p><br>"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let attributedText = originText.htmlToAttributedStringWithAttributes(font: UIFont(name: "HiraginoSans-W3", size: 20)!, color: UIColor(ciColor: .blue))
        testLabel.attributedText = attributedText
    }
}
extension String {
    func htmlToAttributedStringWithAttributes(font: UIFont, color: UIColor) -> NSMutableAttributedString? {
            let htmlTemplate = """
            <!doctype html>
            <html>
              <head>
                <style>
                  body {
                    font-family: \(font.fontName);
                    font-size: \(font.pointSize)px;
                    color: \(color.hexString);
                  }
                </style>
              </head>
              <body>
                \(self)
              </body>
            </html>
            """

            guard let data = htmlTemplate.data(using: .utf8) else { return nil }

            let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
                .documentType: NSAttributedString.DocumentType.html,
                .characterEncoding: String.Encoding.utf8.rawValue
            ]

            return try? NSMutableAttributedString(data: data, options: options, documentAttributes: nil)
        }
}
extension UIColor {
    var hexString: String {
        let components = self.cgColor.components!
        let r = components[0]
        let g = components[1]
        let b = components[2]
        let a = components[3]
        let hexString = String(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
        return hexString
    }
}

本文がhtmlTemplateのbodyとなり、
使いたいfontの種類や、大きさ、色はhtmlTemplate中のstyleになるようにしました。
こうするとdataは完全なHTML文となり、これを変換することができるようになります。

もちろん、普通のテキストを受け取り、Storyboardやコードでテキストを表示することが一番ですが、
不可避にこのようにHTML形式のテキストを受け取らないといけない状況が来た時はぜひ使ってみてください。
より良い方法がありますと、コメントで教えてください!
あなたの心優しいコメントがニュービ開発者に力となります。
長い文読んでくださってありがとうございました。

1
0
1

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
1
0