私はUIWebView
のインスタンスを使用してテキストを処理し、正しく色付けします。結果をHTMLとして返しますが、UIWebView
で表示するのではなく、NSAttributedString
でCore Text
を使用して表示します。
NSAttributedString
を作成して描画することはできますが、HTMLをどのように変換して属性付き文字列にマッピングできるかわかりません。
Mac OS XではNSAttributedString
にはinitWithHTML:
メソッドがありますが、これはMac専用の追加であり、iOSでは使用できないことを理解しています。
私もこれに似た質問があることを知っていますが、答えはありませんでしたが、私はもう一度試して、誰かがこれを行う方法を作成したかどうか、そうであれば、共有できるかどうかを確認します。
IOS 7では、UIKitは initWithData:options:documentAttributes:error: メソッドを追加しました。このメソッドは、HTMLを使用してNSAtttributedStringを初期化できます。例:
[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
documentAttributes:nil error:nil];
Swiftの場合:
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)
GithubのOliver Drobnikによる進行中の作業 NSAttributedStringへのオープンソースの追加 があります。 NSScannerを使用してHTMLを解析します。
更新:NSAttributedString HTMLレンダリングは内部のWebKitに依存しており、メインスレッドで実行する必要があることが判明しましたまたは時折SIGTRAPでアプリをクラッシュさせます。
New Relicクラッシュログ:
以下は更新されたthread-safeSwift 2文字列拡張です:
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
}
出力:
私は、これをNSAttributedString
ではなくString
の拡張として追加するつもりでした。静的拡張機能および初期化子として試してみました。私は以下に含めたイニシャライザを好みます。
Swift 4
internal convenience init?(html: String) {
guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
return nil
}
guard let attributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
return nil
}
self.init(attributedString: attributedString)
}
Swift
extension NSAttributedString {
internal convenience init?(html: String) {
guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
return nil
}
guard let attributedString = try? NSMutableAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {
return nil
}
self.init(attributedString: attributedString)
}
}
例
let html = "<b>Hello World!</b>"
let attributedString = NSAttributedString(html: html)
これはSwiftで記述されたString
拡張機能であり、HTML文字列を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を追加しました。
簡単:NSAttributedString
が使用するデフォルトのエンコーディングはNSUTF16StringEncoding
(UTF8ではありません!)です。
Swift 4
extension NSAttributedString {
convenience init(htmlString html: String) throws {
try self.init(data: Data(html.utf8), options: [
.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: String.Encoding.utf8.rawValue
], documentAttributes: nil)
}
}
使用法
UILabel.attributedText = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!")
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
}
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 }
あなたが今持っている唯一の解決策は、HTMLを解析し、与えられたポイント/フォント/などの属性でいくつかのノードを構築し、それらを結合してNSAttributedStringにすることです。それは多くの作業ですが、正しく行われた場合、将来再利用できる可能性があります。
上記の解決策は正しいです。
[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
documentAttributes:nil error:nil];
ただし、iOS 8.1、2、または3で実行している場合、アプリはクラッシュします
クラッシュを回避するためにできることは、これをキューで実行することです。常にメインスレッド上にあるようにします。
Swift:
これを試してください:
extension String {
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
}
}
そして使用するため:
let str = "<h1>Hello bro</h1><h2>Come On</h2><h3>Go sis</h3><ul><li>ME 1</li><li>ME 2</li></ul> <p>It is me bro , remember please</p>"
self.contentLabel.attributedText = str.htmlAttributedString()
NSHTMLTextDocumentTypeの使用は遅く、スタイルを制御するのは困難です。 Atributikaと呼ばれる私のライブラリを試してみることをお勧めします。独自の非常に高速なHTMLパーサーがあります。また、タグ名を付けて、スタイルを定義することもできます。
例:
let str = "<strong>Hello</strong> World!".style(tags:
Style("strong").font(.boldSystemFont(ofSize: 15))).attributedString
label.attributedText = str
ここで見つけることができます https://github.com/psharanda/Atributika
フォント付き
extension NSAttributedString
{
internal convenience init?(html: String, font: UIFont? = nil) {
guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {
return nil
}
assert(Thread.isMainThread)
guard let attributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) else {
return nil
}
let mutable = NSMutableAttributedString(attributedString: attributedString)
if let font = font {
mutable.addAttribute(.font, value: font, range: NSRange(location: 0, length: mutable.length))
}
self.init(attributedString: mutable)
}
}
あるいは、これが派生したバージョンを使用し、attributedStringを設定した後にUILabelにフォントを設定できます
このスレッド、ポッド、およびiOS Gourmet Cookbook p.80のErica SadunのObjCの例に触発されて、HTMLプレーン文字列とNSAttributedStringsの間を行き来するString
およびNSAttributedString
に拡張機能を作成しましたそしてその逆-GitHubで ここ 、これは有用だとわかった。
シグネチャは次のとおりです(ここでも、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 }