163

のインスタンスを使用してUIWebViewテキストを処理し、正しく色付けしています。結果は HTML として表示されますUIWebViewCore TextNSAttributedString

を作成して描画することはできますNSAttributedStringが、HTML を属性付き文字列に変換してマップする方法がわかりません。

NSAttributedStringMac OS Xにはメソッドがあることは理解してinitWithHTML:いますが、これは Mac のみの追加であり、iOS では使用できません。

これと同様の質問があることも知っていますが、回答がありませんでした.

4

17 に答える 17

305

iOS 7 では、UIKit はHTML を使用してinitWithData:options:documentAttributes:error:初期化できるメソッドを追加しました。NSAttributedString

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

スウィフトの場合:

let htmlData = NSString(string: details).data(using: String.Encoding.unicode.rawValue)
let options = [NSAttributedString.DocumentReadingOptionKey.documentType:
        NSAttributedString.DocumentType.html]
let attributedString = try? NSMutableAttributedString(data: htmlData ?? Data(),
                                                          options: options,
                                                          documentAttributes: nil)
于 2013-09-19T05:21:28.340 に答える
47

GithubのOliverDrobnikによるNSAttributedStringへの進行中のオープンソースの追加があります。HTML解析にNSScannerを使用します。

于 2011-01-10T23:03:42.270 に答える
32

HTML からの NSAttributedString の作成は、メイン スレッドで行う必要があります。

更新: NSAttributedString HTML レンダリングは内部で WebKit に依存しており、メイン スレッドで実行する必要があることが判明しました。そうしない と、 SIGTRAP でアプリがクラッシュすることがあります。

New Relic クラッシュ ログ:

ここに画像の説明を入力

以下は、更新されたスレッドセーフなSwift 2 String 拡張機能です。

extension String {
    func attributedStringFromHTML(completionBlock:NSAttributedString? ->()) {
        guard let data = dataUsingEncoding(NSUTF8StringEncoding) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        let options = [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
                   NSCharacterEncodingDocumentAttribute: NSNumber(unsignedInteger:NSUTF8StringEncoding)]

        dispatch_async(dispatch_get_main_queue()) {
            if let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) {
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

使用法:

let html = "<center>Here is some <b>HTML</b></center>"
html.attributedStringFromHTML { attString in
    self.bodyLabel.attributedText = attString
}

出力:

ここに画像の説明を入力

于 2015-12-09T23:25:40.787 に答える
12

これは、StringHTML 文字列を として返すために Swift で作成された拡張機能ですNSAttributedString

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.dataUsingEncoding(NSUTF16StringEncoding, allowLossyConversion: false) else { return nil }
        guard let html = try? NSMutableAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
        return html
    }
}

使用するには、

label.attributedText = "<b>Hello</b> \u{2022} babe".htmlAttributedString()

上記では、ユニコードを正しくレンダリングすることを示すために、意図的にユニコード \u2022 を追加しました。

些細なこと: 使用するデフォルトのエンコーディングNSAttributedStringNSUTF16StringEncoding(UTF8 ではありません!)。

于 2016-05-25T03:23:33.170 に答える
6

Andrewのソリューションにいくつかの変更を加え、コードを Swift 3 に更新します。

このコードは UITextView を使用しself、元のフォント、フォント サイズ、テキストの色を継承できるようになりました。

注:ここtoHexString()からの延長です

extension UITextView {
    func setAttributedStringFromHTML(_ htmlCode: String, completionBlock: @escaping (NSAttributedString?) ->()) {
        let inputText = "\(htmlCode)<style>body { font-family: '\((self.font?.fontName)!)'; font-size:\((self.font?.pointSize)!)px; color: \((self.textColor)!.toHexString()); }</style>"

        guard let data = inputText.data(using: String.Encoding.utf16) else {
            print("Unable to decode data from html string: \(self)")
            return completionBlock(nil)
        }

        DispatchQueue.main.async {
            if let attributedString = try? NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) {
                self.attributedText = attributedString
                completionBlock(attributedString)
            } else {
                print("Unable to create attributed string from html string: \(self)")
                completionBlock(nil)
            }
        }
    }
}

使用例:

mainTextView.setAttributedStringFromHTML("<i>Hello world!</i>") { _ in }
于 2017-01-07T07:52:52.997 に答える
5

Swift 3.0 Xcode 8 バージョン

func htmlAttributedString() -> NSAttributedString? {
    guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
    guard let html = try? NSMutableAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) else { return nil }
    return html
}
于 2016-09-28T18:19:48.267 に答える
3

あなたが現在持っている唯一の解決策は、HTML を解析し、指定されたポイント/フォント/etc 属性を持ついくつかのノードを構築し、それらを NSAttributedString に結合することです。大変な作業ですが、正しく行えば、将来再利用できるようになります。

于 2010-11-18T17:42:03.743 に答える
2

上記の解決策は正しいです。

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] 
                                 options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                           NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} 
                      documentAttributes:nil error:nil];

ただし、ios 8.1、2、または 3 で実行している場合、アプリはクラッシュします。

クラッシュを回避するには、これをキューで実行します。常にメインスレッドにあるようにします。

于 2015-12-30T07:00:02.320 に答える
0

便利な拡張機能

このスレッド、ポッド、および iOS Gourmet Cookbook p.80 の Erica Sadun の ObjC の例に触発されて、HTML プレーン文字列と NSAttributedStrings の間、およびその逆を行き来するための拡張機能を何StringNSAttributedString書きました。私は役に立ちました。

署名は次のとおりです (ここでも、Gist の完全なコード、上記のリンク)。

extension NSAttributedString {
    func encodedString(ext: DocEXT) -> String?
    static func fromEncodedString(_ eString: String, ext: DocEXT) -> NSAttributedString? 
    static func fromHTML(_ html: String) -> NSAttributedString? // same as above, where ext = .html
}

extension String {
    func attributedString(ext: DocEXT) -> NSAttributedString?
}

enum DocEXT: String { case rtfd, rtf, htm, html, txt }
于 2016-09-18T03:57:52.720 に答える