NSString: strip out <b></b> and make an attributed string with color for that segment?

一个人想着一个人 提交于 2021-01-02 06:13:39

问题


Say if I have a string:

This is a < b >simple < /b > string.

I need to get rid of the < b >, (sorry there is no space between b and angle bracket, for some reason the preview does not show it), also make the word 'simple' to be bold, my thought was:

  1. replace the angle brackets and br with empty space
  2. make the 'simple' segment to have attributes

The problem is once the tags are removed, I still need to know the word's location, do I first remember the location of 'simple', after removal, the location-4 should be the new location of 'simple'? Is there any better way? Or even transform html tag to attributes?

Thanks

edit: Should be b instead of br


回答1:


There is API available in iOS 7 that makes this very easy. It will convert an NSString of (possible) HTML text to an NSAttributedString.

NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType };

NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithData:[myHTMLString dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:nil];

It will even preserve any in-line CSS applied, even background-color!

Note that if no font and font size is specified in the HTML text, the default will be Times New Roman 12. You could specify it in this fashion: <style>body { font-family:-apple-system; font-size:14px; }<style>. If you do not specify the font via CSS, you can still override the font, but you will need to manually handle bold, italics, etc otherwise that formatting will be lost if you set the font for the entire string. One approach is to enumerateAttribute: NSFontAttributeName on the mutable attributed string looking for 'bold' etc in the font name, and if it's found then replace that range with the desired font, such as the user's preferred font and size but the bold etc version of it, and continue replacing fonts with each range obtained from the enumeration.




回答2:


The current answer is OK, and I have +1'd it. Yet it was only a clue, not a real solution. If you are looking for a solution to the OP's question, take a look here.

You should focus on the following:

First implement these methods:

- (NSString *)styledHTMLwithHTML:(NSString *)HTML {
    NSString *style = @"<meta charset=\"UTF-8\"><style> body { font-family: 'HelveticaNeue'; font-size: 20px; } b {font-family: 'MarkerFelt-Wide'; }</style>";

    return [NSString stringWithFormat:@"%@%@", style, HTML];
}

- (NSAttributedString *)attributedStringWithHTML:(NSString *)HTML {
    NSDictionary *options = @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType };
    return [[NSAttributedString alloc] initWithData:[HTML dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL error:NULL];
}

Later use them like that:

// This is a string that you might find in your model
NSString *html = @"This is <b>bold</b>";

// Apply some inline CSS
NSString *styledHtml = [self styledHTMLwithHTML:html];

// Generate an attributed string from the HTML
NSAttributedString *attributedText = [self attributedStringWithHTML:styledHtml];

// Set the attributedText property of the UILabel
label.attributedText = attributedText;



回答3:


Similar to Michael's answer just updated for latest swift version,

extension UILabel {
    func setHTMLFromString(htmlText: String) {
        // Apply some inline CSS
        let style = "<meta charset=\"UTF-8\"><style> body { font-family: 'TheSansArabic-Plain'; font-size: 12px; } b {font-family: 'TheSansArabic-Bold'; font-size: 12px; } </style>"
        let styledHtml = style + htmlText
        // Generate an attributed string from the HTML
        let attributedText = try? NSAttributedString(data: styledHtml.data(using: .utf8)!, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)
        // Set the attributedText property of the UILabel
        self.attributedText = attributedText
    }
}

Use In your code like this,

override func viewDidLoad() {
    super.viewDidLoad()
    label.setHTMLFromString(htmlText: "This is <b>BOLD text</b>")
}



回答4:


Use this method (Swift 5):

extension Swift {
    // Color all strings between two tags and remove the tags
    mutating func colorSubstringsBetweenTags(start: String, end: String, color: UIColor, font: UIFont? = nil) -> NSAttributedString {
        var string = self
        let attribute = NSMutableAttributedString(string: string)
        
        while let openedEm = string.range(of: start, range: string.startIndex..<string.endIndex) {
            let substringFrom = openedEm.upperBound
            guard let closedEm = string.range(of: end, range: openedEm.upperBound..<string.endIndex) else { return attribute }
            let substringTo = closedEm.lowerBound
            let nsrange = NSRange(substringFrom..<substringTo, in: string)
            if let font = font { attribute.addAttributes([.font: font], range: nsrange) }
            attribute.addAttribute(.foregroundColor, value: color, range: nsrange)
            attribute.mutableString.replaceCharacters(in: NSRange(closedEm, in: string), with: "")
            attribute.mutableString.replaceCharacters(in: NSRange(openedEm, in: string), with: "")
            string = attribute.mutableString as String
        }
        
        return attribute
    }
}

Usage:

 var text = "some text with <b>tags</b> or other <b>TAG</b>"
 yourLabel.attributedText = text.colorSubstringsBetweenTags(start: "<b>", end: "</b>", color: .red)


来源:https://stackoverflow.com/questions/18667603/nsstring-strip-out-b-b-and-make-an-attributed-string-with-color-for-that-se

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!