[iphone] iOS에서 HTML을 NSAttributedString으로 변환

UIWebView일부 텍스트를 처리하고 올바르게 색상을 지정 하는 인스턴스를 사용 하고 있습니다. 결과는 HTML로 표시되지만에 표시하지 않고 HTML UIWebView로 표시하고 싶습니다 Core Text.NSAttributedString .

나는 만들 수 있고 NSAttributedString 있지만 HTML을 중요한 문자열로 변환하고 매핑하는 방법을 잘 모르겠습니다.

Mac OS X NSAttributedString에서는initWithHTML: 방법이 있지만 Mac 전용이며 iOS에서는 사용할 수 없다는 있습니다.

나는 이것과 비슷한 질문이 있다는 것을 알고 있지만 대답이 없었습니다. 나는 다시 시도하고 누군가가 이것을 할 수있는 방법을 만들 었는지, 만약 그렇다면 공유 할 수 있는지 확인했습니다.



답변

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)


답변

Github의 Oliver Drobnik 가 NSAttributedString 에 진행중인 오픈 소스 추가 작업이 있습니다 . HTML 구문 분석을 위해 NSScanner를 사용합니다.


답변

HTML에서 NSAttributedString을 생성하는 것은 메인 스레드에서 수행되어야합니다!

업데이트 : NSAttributedString HTML 렌더링은 후드 아래의 WebKit에 의존 하며 기본 스레드에서 실행해야 하거나 때로는 SIGTRAP으로 앱이 충돌합니다 .

새로운 유물 충돌 로그 :

여기에 이미지 설명을 입력하십시오

아래는 업데이트 된 스레드 안전 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
}

산출:

여기에 이미지 설명을 입력하십시오


답변

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)


답변

이것은 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 아님!)입니다.


답변

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 }


답변

스위프트 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
}