ios native加载H5图片(转载)

本文转自标哥的技术博客

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

NSRegularExpression regex = [NSRegularExpression regularExpressionWithPattern:@"]/>" 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"];

然后,我们需要遍历所有匹配到的
标签,并提取出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);
}

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

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

NSRegularExpression(pattern: "]*/>", 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

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

1
2
3
4
5

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

你可能感兴趣的:(ios native加载H5图片(转载))