سؤال

أنا أستخدم مثيل UIWebView لمعالجة بعض النص واللون بشكل صحيح ، فإنه يعطي النتيجة HTML ولكن بدلاً من عرضه في UIWebView أريد عرضه باستخدام Core Text مع NSAttributedString.

أنا قادر على إنشاء ورسم NSAttributedString لكنني غير متأكد من كيفية تحويل HTML ورسم خريطة إلى السلسلة المنسوبة.

أنا أفهم أنه تحت نظام التشغيل Mac OS X NSAttributedString لديه initWithHTML: الطريقة ولكن هذه كانت إضافة Mac فقط وليست متوفرة لنظام iOS.

أعلم أيضًا أن هناك سؤالًا مشابهًا لهذا ولكن لم يكن لديه إجابات ، على الرغم من أنني سأحاول مرة أخرى وأرى ما إذا كان أي شخص قد خلق طريقة للقيام بذلك وإذا كان الأمر كذلك ، وإذا كان بإمكانهم مشاركته.

هل كانت مفيدة؟

المحلول

في iOS 7 ، أضاف Uikit initWithData:options:documentAttributes:error: الطريقة التي يمكن تهيئة NSAtttributedString باستخدام HTML ، على سبيل المثال:

[[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)

نصائح أخرى

هناك عمل محدود إضافة مفتوح المصدر إلى nsattributedString بقلم أوليفر دروبنيك في جيثب. ويستخدم nsscanner لتحليل HTML.

يجب أن يتم إنشاء nsattributedString من HTML على الخيط الرئيسي!

تحديث: اتضح أن عرض NSATTributedString HTML يعتمد على WebKit أسفل الغطاء ، و يجب تشغيل على الموضوع الرئيسي أو سوف يعطل التطبيق أحيانًا باستخدام sigtrap.

سجل تصادم جديد:

enter image description here

أدناه محدث آمن الخيط امتداد سلسلة Swift 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
}

انتاج:

enter image description here

امتداد مُعمى سريع على nsattributedString

كان ميلي لإضافة هذا كامتداد إلى NSAttributedString عوضا عن String. جربته كامتداد ثابت ومهيج. أنا أفضل المُهيئ وهو ما قمت بتضمينه أدناه.

سريع 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)
}

سريع 3

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)

هذا ال 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()

في ما سبق ، أضفت عمداً Unicode u2022 لإظهار أنه يجعل Unicode بشكل صحيح.

تافهة: الترميز الافتراضي ذلك NSAttributedString الاستخدامات NSUTF16StringEncoding (ليس UTF8!).

إصدار 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
}

سريع 4


  • nsattributedstring التهيئة
  • بدون حراس إضافيين
  • يرمي الخطأ

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!")

الحل الوحيد الذي لديك الآن هو تحليل HTML ، وبناء بعض العقد مع سمات نقطة/خط/إلخ ، ثم الجمع بينها في NSATTributedString. إنه الكثير من العمل ، ولكن إذا تم القيام به بشكل صحيح ، يمكن إعادة استخدامه في المستقبل.

إجراء بعض التعديل على أندروحل وتحديث الرمز إلى 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 }

الحل أعلاه صحيح.

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

لكن التطبيق مع تعطله إذا كنت تقوم بتشغيله على iOS 8.1،2 أو 3.

لتجنب التعطل ما يمكنك فعله هو: تشغيل هذا في قائمة الانتظار. بحيث يكون دائما على الموضوع الرئيسي.

استخدام 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

سريع 3:
جرب هذا:

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()

ملحقات مفيدة

مستوحى من هذا الموضوع ، قرنة ، ومثال OBJC الخاص بـ Erica Sadun في كتاب طبخ iOS Gourmet P.80 ، كتبت تمديدًا على String و على NSAttributedString للذهاب ذهابًا وإيابًا بين السلاسل العادية HTML و NSATTributedStrings والعكس-على Github هنا, ، والتي وجدت مفيدة.

ال التوقيعات هي (مرة أخرى ، رمز كامل في جوهر ، الرابط أعلاه):

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 }

مع الخط

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)
}
}

بدلاً من ذلك ، يمكنك استخدام الإصدارات التي تم اشتقاقها من الخط على Uilabel بعد الإعداد

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top