加载 html string很简单,就是UILabel 或 UITextView attributedText
属性。
其中的 attributedText
用以下方式来创建:
NSAttributedString *tmpString = [[NSMutableAttributedString alloc] initWithData:[htmlText dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil];
当然也可以用 UIWebView
。
然而问题来了,html string 中包含网络资源图片用无法加载。文字内容能很好的展示,图片的位置也空出来了,但就是无法显示。
这是一个没法回避的问题。网上搜遍,没有现成的代码利用。只能跟着只言片语组合。一天的琢磨,终于解决。
思路:
- 抽出
html
中的img标签
对应的url
保存到数组imageURLs
中, 同时记住img标签
的range
(NSRange转 NSString)添加到ranges
中 (这个网上有现成的方法,我也进行了借鉴和优化)。 - 利用
ranges
将html
中的img标签
剔除并分割,并将剩余的内容添加到数组substrings
中。 - 利用
substrings
和imageURLs
组成新的NSAttributedString
。
效果如下:( 帖子详情
中,最上面的图片是个 imageview,其他所有内容包括图片为一个 label 展示的)
示例
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
最后,希望这点分享能够帮到您。如果有其他更好的方法,欢迎积极探讨。