ios native加载H5图片(转载)

本文转自标哥的技术博客

首先,我们要获取HTML内容,并通过正则表达式来匹配出所有的<img src="..."/>
的标签:
NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
NSString *html = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

NSRegularExpression regex = [NSRegularExpression regularExpressionWithPattern:@"<img\ssrc[^>]/>" options:NSRegularExpressionAllowCommentsAndWhitespace error:nil];

NSArray *result = [regex matchesInString:html options:NSMatchingReportCompletion range:NSMakeRange(0, html.length)];

接下来,我们需要一个字典来存储HTML原始的URL和与之关联的本地URL。由于使用原始URL的md5值作为文件名字,因此本地路径也就唯一确定了。这里就将图片都放到Document下。

NSMutableDictionary *urlDicts = [[NSMutableDictionary alloc] init];
NSString *docPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

然后,我们需要遍历所有匹配到的<img src="..."/>
标签,并提取出Src属性值,也就是我们要的原始URL。将并该URL存储下来,以便下一步替换。

for (NSTextCheckingResult *item in result) {
NSString *imgHtml = [html substringWithRange:[item rangeAtIndex:0]];

NSArray *tmpArray = nil;
if ([imgHtml rangeOfString:@"src=\""].location != NSNotFound) {
  tmpArray = [imgHtml componentsSeparatedByString:@"src=\""];
} else if ([imgHtml rangeOfString:@"src="].location != NSNotFound) {
  tmpArray = [imgHtml componentsSeparatedByString:@"src="];
}
    
if (tmpArray.count >= 2) {
  NSString *src = tmpArray[1];
  
  NSUInteger loc = [src rangeOfString:@"\""].location;
  if (loc != NSNotFound) {
    src = [src substringToIndex:loc];
    
    NSLog(@"正确解析出来的SRC为:%@", src);
    if (src.length > 0) {
      NSString *localPath = [docPath stringByAppendingPathComponent:[self md5:src]];
      // 先将链接取个本地名字,且获取完整路径
      [urlDicts setObject:localPath forKey:src];
    }
  }
}

}

下一步,我们需要将HTML中所有的原始src的url值替换成我们app的沙盒中的图片路径,如果该路径中未存在,则需要去下载图片,否则不需要重复下载。如下:

// 遍历所有的URL,替换成本地的URL,并异步获取图片
for (NSString *src in urlDicts.allKeys) {
NSString *localPath = [urlDicts objectForKey:src];
html = [html stringByReplacingOccurrencesOfString:src withString:localPath];

// 如果已经缓存过,就不需要重复加载了。
if (![[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
  [self downloadImageWithUrl:src];
}

}

下载图片后,还需要将图片存储到该原始url对应的本地路径,也就是Document下,其文件名为原始url的md5值,其他也就可以得出去唯一路径。这里只贴出存储代码,关于如何下载图片,查看demo。

NSData *data = UIImagePNGRepresentation(image);
NSString *docPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];

NSString *localPath = [docPath stringByAppendingPathComponent:[self md5:src]];

if (![data writeToFile:localPath atomically:NO]) {
NSLog(@"写入本地失败:%@", src);
}

难点
这里有几处难点:
如何匹配<img src="..."/>
来查找图片链接
在匹配到以后,如何获取src的值
在得到src的值以后,如何在iOS原生获取图片后让webview加载

这里使用了正则表达式来匹配查找<img src="..."/>
,匹配结果可能有多个,遍历数组就可以处理所有的图片链接:

NSRegularExpression(pattern: "<img\ssrc[^>]*/>", options: .AllowCommentsAndWhitespace

存储图片到沙盒
通过获取到HTML中图片的链接后,我们需要通过ios原生的方式来发起请求,加载图片,在加载完成后,我们需要将图片存储到沙盒中document下:

func saveImageData(data: NSData, name: String) ->String {
let docPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as NSString

let path = docPath.stringByAppendingPathComponent(name)

// 若已经缓存过,就不需要重复操作了
if NSFileManager.defaultManager().fileExistsAtPath(path) {
return path
}

do {
try data.writeToFile(path, options: NSDataWritingOptions.DataWritingAtomic)
} catch {
print("save image data with name: (name) error")
}

return path
}

验证是否成功
首先我们可以看到test.html中只有两个img标签:

1
2
3
4
5

<img src="http://www.jhjcqc.com/ueditor/php/upload/image/20151014/1444783819412910.jpg" />

<img src="http://www.jhjcqc.com/ueditor/php/upload/image/20151014/1444783847836404.jpg" />

在我们替换路径完成后,我们加载webview,然后打印出webview所加载的HTML内容中这两个<img>
标签的src是否变化,结果如下:

1
2
3
4
5

<img src="/Users/huangyibiao/Library/Developer/CoreSimulator/Devices/09692E07-2E79-4070-9537-CFD9F3141B0D/data/Containers/Data/Application/73F6D429-E0FD-4BD4-B0A5-85C1BD179840/Documents/5353c07f4c2ea0471b9f3ee36dedcaac" />

<img src="/Users/huangyibiao/Library/Developer/CoreSimulator/Devices/09692E07-2E79-4070-9537-CFD9F3141B0D/data/Containers/Data/Application/73F6D429-E0FD-4BD4-B0A5-85C1BD179840/Documents/54edea1f2edd444aaba9d0321d786962" />

根据效果图,我们可以看到图片是显示出来了,这就说明替换成功后仍然可以加载出来图片,实验成功。
源代码
想要下载源代码,请移步github下载,内有Swift版的工程和ObjC版的工程:https://github.com/CoderJackyHuang/iOSLoadWebViewImage

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容