UILabel 或 UITextView 加载有网络图片的 html String

加载 html string很简单,就是UILabel 或 UITextView attributedText属性。

其中的 attributedText用以下方式来创建:

NSAttributedString *tmpString = [[NSMutableAttributedString alloc] initWithData:[htmlText dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];

当然也可以用 UIWebView

然而问题来了,html string 中包含网络资源图片用无法加载。文字内容能很好的展示,图片的位置也空出来了,但就是无法显示。

这是一个没法回避的问题。网上搜遍,没有现成的代码利用。只能跟着只言片语组合。一天的琢磨,终于解决。

思路:

  1. 抽出 html 中的 img标签 对应的 url 保存到数组 imageURLs 中, 同时记住 img标签range(NSRange转 NSString)添加到 ranges 中 (这个网上有现成的方法,我也进行了借鉴和优化)。
  2. 利用 rangeshtml 中的 img标签 剔除并分割,并将剩余的内容添加到数组 substrings 中。
  3. 利用 substringsimageURLs 组成新的 NSAttributedString

效果如下:( 帖子详情 中,最上面的图片是个 imageview,其他所有内容包括图片为一个 label 展示的)

UILabel 或 UITextView 加载有网络图片的 html String_第1张图片
image

示例

self.contentLabel.attributedText = [HTMLHelper attributedTextFromHTML:html];

具体代码:

HTMLHelper.h

#import 

@interface HTMLHelper : NSObject

/**
 解析原始的 html string 为 NSAttributedString

 @param originHtml html标签 string
 @return NSAttributedString
 */
+ (NSAttributedString *)attributedTextFromHTML:(NSString *)originHtml;
@end

HTMLHelper.m


#import "HTMLHelper.h"
@interface HTMLHelper ()

@end

@implementation HTMLHelper

//获取webView中的所有图片URL
- (NSArray *)getImageurlFromHtml:(NSMutableAttributedString *) webString {
    NSMutableArray *imageurlArray = [[NSMutableArray alloc] init];
    NSMutableArray *ranges = [[NSMutableArray alloc] init];
    if (webString.length==0) {
        return nil;
    }
    NSString *webStr  = [webString.string copy];

    //标签匹配
    NSString *parten = @"";
    NSError* error = NULL;
    NSRegularExpression *reg = [NSRegularExpression regularExpressionWithPattern:parten options:0 error:&error];

    NSArray* match = [reg matchesInString:webStr options:0 range:NSMakeRange(0, [webString length] - 1)];

    for (NSTextCheckingResult * result in match) {

        //过去数组中的标签
        NSRange range = [result range];
        NSString *rangeString = NSStringFromRange(range);
        NSLog(@"-------add item:%@", rangeString);
        [ranges addObject:rangeString];
        NSString * subString = [webStr substringWithRange:range];


        //从图片中的标签中提取ImageURL
        NSRegularExpression *subReg = [NSRegularExpression regularExpressionWithPattern:@"http://(.*?)\"" options:0 error:NULL];
        NSArray* match = [subReg matchesInString:subString options:0 range:NSMakeRange(0, [subString length] - 1)];

        NSRegularExpression *subRegOne = [NSRegularExpression regularExpressionWithPattern:@"https://(.*?)\"" options:0 error:NULL];
        NSArray *matchOne = [subRegOne matchesInString:subString options:0 range:NSMakeRange(0, [subString length] - 1)];
        NSMutableArray *tmpItems = [[NSMutableArray alloc] init];
        if (match.count > 0) {
            [tmpItems addObjectsFromArray:match];
        }
        if (matchOne.count > 0) {
            [tmpItems addObjectsFromArray:matchOne];

        }
        if (tmpItems.count > 0) {
            NSTextCheckingResult * subRes = tmpItems[0];
            NSRange subRange = [subRes range];
            subRange.length = subRange.length -1;
            NSString * imagekUrl = [subString substringWithRange:subRange];

            //将提取出的图片URL添加到图片数组中
            [imageurlArray addObject:imagekUrl];
        }
    }
    return imageurlArray;
}

+ (NSAttributedString *)attributedTextFromHTML:(NSString *)html {
    if (html.length == 0 ) {
        return [[NSAttributedString alloc] init];
    }
    NSMutableString *mutableHtml = [html mutableCopy];
    NSMutableArray *subStrings = [[NSMutableArray alloc] init];
    NSMutableArray *imageurlArray = [[NSMutableArray alloc] init];
    NSMutableArray *ranges = [[NSMutableArray alloc] init];

    //标签匹配
    NSString *parten = @"";
    NSError* error = NULL;
    NSRegularExpression *reg = [NSRegularExpression regularExpressionWithPattern:parten options:0 error:&error];

    NSArray* match = [reg matchesInString:html options:0 range:NSMakeRange(0, [html length] - 1)];
    if (match.count > 0) {
        for (NSTextCheckingResult *result in match) {
            //过去数组中的标签
            NSRange range = [result range];
            NSString *rangeString = NSStringFromRange(range);
            NSLog(@"-------add item:%@", rangeString);
            [ranges addObject:rangeString];
            NSString * subString = [html substringWithRange:range];

            //从图片中的标签中提取ImageURL
            NSRegularExpression *subReg = [NSRegularExpression regularExpressionWithPattern:@"http://(.*?)\"" options:0 error:NULL];
            NSArray* match = [subReg matchesInString:subString options:0 range:NSMakeRange(0, [subString length] - 1)];
            NSRegularExpression *subRegOne = [NSRegularExpression regularExpressionWithPattern:@"https://(.*?)\"" options:0 error:NULL];
            NSArray *matchOne = [subRegOne matchesInString:subString options:0 range:NSMakeRange(0, [subString length] - 1)];
            NSMutableArray *tmpItems = [[NSMutableArray alloc] init];
            if (match.count > 0) {
                [tmpItems addObjectsFromArray:match];
            }
            if (matchOne.count > 0) {
                [tmpItems addObjectsFromArray:matchOne];

            }
            if (tmpItems.count > 0) {
                NSTextCheckingResult * subRes = tmpItems[0];
                NSRange subRange = [subRes range];
                subRange.length = subRange.length -1;
                NSString * imagekUrl = [subString substringWithRange:subRange];

                //将提取出的图片URL添加到图片数组中
                [imageurlArray addObject:imagekUrl];
            }
        }
    }
    ///将 html 按图片分割,并加入数组
    NSLog(@"ranges:%@", ranges.description);
    NSLog(@"imgURLs:%@", imageurlArray.description);
    if (ranges.count > 0) {
        NSUInteger startIndex = html.length;
        NSUInteger length = 0;
        for ( int index = ranges.count - 1; index >= 0; index--) {
            NSLog(@"currentRange:%@", ranges[index]);
            NSLog(@"mutableHtml length:%ld", mutableHtml.length);
            NSRange tmpRange = NSRangeFromString(ranges[index]);
            startIndex = tmpRange.location + tmpRange.length;
            length = mutableHtml.length - startIndex;

            NSLog(@"start index:%ld", startIndex);

            if (startIndex < mutableHtml.length ) {
                NSRange subStringRange = NSMakeRange(startIndex, length);
                NSString *tmpString = [mutableHtml substringWithRange:subStringRange];
                if (subStrings.count == 0) {
                    [subStrings addObject:tmpString];
                } else {
                    [subStrings insertObject:tmpString atIndex:0];
                }
            }
            mutableHtml = [[mutableHtml substringToIndex:tmpRange.location] mutableCopy];
        }
        if (mutableHtml.length > 0) {
            if (subStrings.count == 0) {
                [subStrings addObject:mutableHtml];
            } else {
                [subStrings insertObject:mutableHtml atIndex:0];
            }
        }
    }

    NSMutableAttributedString *terminalString = [HTMLHelper attributedTextFrom:subStrings imgSrcs:imageurlArray];
    return [terminalString copy];
}


/**
 将数组中的字符串和图片资源重组为 AttributedString

 @param subStrings <#subStrings description#>
 @param imgURLs <#imgURLs description#>
 @return <#return value description#>
 */
+ (NSMutableAttributedString *)attributedTextFrom:(NSArray *)subStrings imgSrcs:(NSArray *)imgURLs {
    NSMutableAttributedString *string  = [[NSMutableAttributedString alloc] init];
    if (subStrings.count > 0) {
        for (int index = 0; index < subStrings.count; index++) {
            NSAttributedString *tmpString = [[NSMutableAttributedString alloc] initWithData:[subStrings[index] dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];
            [string appendAttributedString:tmpString];
            if (imgURLs.count > index) {

                NSTextAttachment *attach = [[NSTextAttachment alloc] init];

                NSString *imageUrlStr = imgURLs[index];

                NSURL *url = [NSURL URLWithString:imageUrlStr];

                NSData *imageData = [NSData dataWithContentsOfURL:url];
                UIImage *image = [UIImage imageWithData:imageData];
                attach.image = image;

                CGSize size = CGSizeMake(kScreen_Width - 10, image.size.height / image.size.width * kScreen_Width);

                attach.bounds = CGRectMake(0, 0, size.width, size.height);

                NSAttributedString *attachString = [NSAttributedString attributedStringWithAttachment:attach];

                // 点击图片跳转到safari
                NSMutableAttributedString *maImageStr = [[NSMutableAttributedString alloc] initWithAttributedString:attachString];

                [maImageStr addAttribute:NSLinkAttributeName value:url.absoluteString range:NSMakeRange(0, maImageStr.length)];
                [string appendAttributedString:maImageStr];
            }
        }
    }
    return string;
}

@end

最后,希望这点分享能够帮到您。如果有其他更好的方法,欢迎积极探讨。

你可能感兴趣的:(UILabel 或 UITextView 加载有网络图片的 html String)