iOS UIWebView 图片 内存缓存 交互二维码识别

iOS UIWebView 图片 内存缓存 交互二维码识别

最近公司项目开发遇到了原生与js交互的问题,讲义是webview,里边有些图片需要查看。相信这个需求很多人都遇到过。那么今天我就仔细帮你梳理下。那些还在为这个功能头疼的,请继续看,或者你直接拷贝代码使用。这个功能需要以下几个步骤:
获取图片,获取图片URL ,获取图片frame 把获取的图片展示在window上*

我们先从获取图片说起

写在前边 JS 交互的问题呢,如果是小白,请看这里。

所有的JS ,都要写在
webViewDidFinishLoad 这个UIWebView的代理方法中。需要注入JS 。例如
获取image的JS

-(void)webViewDidFinishLoad:(UIWebView *)webView{    
static  NSString * const jsGetImages =
@"function getImages(){\
var objs = document.getElementsByTagName(\"img\");\
var imgScr = '';\
for(var i=0;i<objs.length;i++){\
imgScr = imgScr + objs[i].src + '+';\
};\
return imgScr;\
};";
[webView stringByEvaluatingJavaScriptFromString:jsGetImages];//注入js方法

NSString *urlResurlt = [webView  stringByEvaluatingJavaScriptFromString:@"getImages()"]; // 执行js方法获取urls
}

你处理图片的点击事件需要在这个代理方法中

-(BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType;


获取图片

JS 交互获取图片,需要执行JS。

@"function getImages(){\
        var objs = document.getElementsByTagName(\"img\");\
        var imgScr = '';\
        for(var i=0;i<objs.length;i++){\
            imgScr = imgScr + objs[i].src + '+';\
        };\
    return imgScr;\
};"         

这样获取出来的是一个字符串。一个 以+号拼接的字符串,然后分解下就是全部的imageUrl.

这样你获取了所有的图片,然而并没有什么卵用。 < < !,那就有人说了,我想要的是图片点击,要获取到点击的图片的URL。 好吧。那么下边的JS ,完美的满足了您的需求。

 [self.webView stringByEvaluatingJavaScriptFromString:@"function   registerImageClickAction(){\
 var imgs=document.getElementsByTagName('img');\
 var length=imgs.length;\
 for(var i=0;i<length;i++){\
 img=imgs[i];\
 img.onclick=function(){\
 window.location.href='image-preview:'+this.src}\
 }\
}"];

这样你在shouldStartLoadWithRequest 代理方法中,截获 名字是 image-preview的事件,获得的就是 当前点击的URL

if ([request.URL.scheme isEqualToString:@"image-preview"]) {
    NSString* path = [request.URL.absoluteString substringFromIndex:[@"image-preview:" length]];
    path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    // path就是你要的imageUrl
    }

那么好多人的需求到这里就结束了。 那么还有人说,我想要所有的图片。那么下边的js, 满足你

function getAllImageUrl(){\
    var imgs = document.getElementsByTagName(\"img\");\
    var urlArray = [];\
    for (var i=0;i<imgs.length;i++){\
        var src = imgs[i].src;\
        urlArray.push(src);\
    }\
    return urlArray.toString();\
}\

得到的是一个数组。那么上边的三个JS, 满足了需求,很好,你可以去写你的代码了。那么这里如果想要继续深入了解的同学。请注意。以下内容是 性能优化的,不想了解的朋友直接 把上边的代码拿走就行。如果你还是没看懂那么参考下边这个文章:
http://www.jianshu.com/p/aa2f1dc8dff7

webview 是从网上加载的图片,然后显示这说明什么,说明图片已经在webview的内存缓存中了,那么,我们拿到图片,然后还得自己做缓存,就算是你用SD 。 也还是多了一步得从网上下载图片,这就造成了不必要的损耗,如果图片少,还没问题,如果,类似网易新闻,今日头条这样存在着大量的图片新闻的问题等。就会造成严重的内存问题

获取webview内存中的图片

博主找了很久,最后找到了。一个工具。RNCachingURLProtocol .获取内存中的缓存。具体原理的,webview的图片会用NSURLProtocol 来进行缓存,这个第三方 缓存图片到指定的文件夹
然后,读取指定文件夹来获取webview的缓存,当然,你也不需要了解太多,你拿去用就好 https://github.com/rnapier/RNCachingURLProtocol

当然。如果你特么想了解里边的东西,可以看看这个文章

http://blog.csdn.net/youcanping2008/article/details/9240487

或者是这个篇

http://www.jianshu.com/p/11664f0a69aa

那么,当你看完了, 以上几篇 ,还是不会用。请看下边。这么使用。。。。

在 didFinishLaunchingWithOptions 中,注册 [NSURLProtocol registerClass:[RNCachingURLProtocol class]];

然后在 shouldStartLoadWithRequest UIWebView的这个代理中直接获取就行了

NSString *fileName = [RNCachingURLProtocol cachePathForURLString:imgUrl];
RNCachedData *memoryCache = [NSKeyedUnarchiver unarchiveObjectWithFile:fileName];

memoryCache 这个就是内存缓存,那图片缓存呢。。看下边

imageView.image = [UIImage imageWithData:memoryCache.data];

这样就可以了。

以上就完美的解决了,交互图片,内存问题。 下边是扩展

获取图片的frame

如果有的朋友,想做一些动画效果,例如放大缩小,需要用到图片的frame。那么你可以看下去。使用下边的JS ,可以获得图片的frame

function getImageRect(i){\
var imgs = document.getElementsByTagName(\"img\");\
var rect;\
rect = imgs[i].getBoundingClientRect().left+\"::\";\
rect = rect+imgs[i].getBoundingClientRect().top+\"::\";\
rect = rect+imgs[i].width+\"::\";\
rect = rect+imgs[i].height;\
return rect;\
}\

这个获取的frame就是你需要的frame,一个相对位置,这个frame你不需要在convert ,你拿到的就是相对路径,是正确的,想具体理解的,百度 : getBoundingClientRect。

那么聪明的朋友已经获取了。点击图片的frame ,但是发现,怎么这个frame MMP的不对呢。动画都特么飞天上去了。位置都不对!!你是不是坑爹呢。请注意,我说了,这个frame是绝对正确的,那么问题出在哪?。大多数的webview 我们都会设置一个属性scalesPageToFit。自适应,就是这个属性导致我们得到的frame是有问题的,那么怎么解决的。

这样我们需要得到一个缩放的比率。然后把frame 乘以这个比率就可以了。代码如下

 NSString *bodyWidth= [webView stringByEvaluatingJavaScriptFromString:  @"document.body.scrollWidth"];
int widthOfBody = [bodyWidth intValue];
CGFloat initialScale = webView.frame.size.width/widthOfBody;

initialScale 就是这个比率 把frame *initialScale 就可以了。这样得到的frame就是 完美的。!

获取手指的点击位置

那么 继续扩展,哈哈哈哈

如果你想获得手指的点击位置那么下边的JS ,适合你

@"document.ontouchstart=function(event){\
x=event.targetTouches[0].clientX;\
y=event.targetTouches[0].clientY;\
document.location=\"myweb:touch:start:\"+x+\":\"+y;};\
document.ontouchmove=function(event){\
x=event.targetTouches[0].clientX;\
y=event.targetTouches[0].clientY;\
document.location=\"myweb:touch:move:\"+x+\":\"+y;};\
document.ontouchcancel=function(event){\
document.location=\"myweb:touch:cancel\";};\
document.ontouchend=function(event){\
document.location=\"myweb:touch:end\";};"

这样你在 处理时间的webview代理中 可以这么写

NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@":"];
if ([components count] > 1 && [(NSString *)[components objectAtIndex:0]
                               isEqualToString:@"myweb"]) {
    if([(NSString *)[components objectAtIndex:1] isEqualToString:@"touch"])
    {
        if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"start"])
        {
            self.gesState = GESTURE_STATE_START;
            NSLog(@"touch start!");

            float ptX = [[components objectAtIndex:3]floatValue];
            float ptY = [[components objectAtIndex:4]floatValue];
            NSLog(@"touch point (%f, %f)", ptX, ptY);

上边的代码不能copy哈,你们自己写,

还有获取手指范围的图片等。具体参照 里边很全,但是他的demo 有问题。哪里有问题,自己找吧。

二维码识别的灯在这篇文章里都有写
http://www.jianshu.com/p/48e44fe67c1d

以上就是分解的 内容,下边,是博主的需求,点击webView 图片放大。只有一个图片,所以我只获取了一张图片。需要动画所以,获取了frame ,具体的代码,如下。小白如果需求跟我一样,直接复制吧

- (void)webViewDidFinishLoad:(UIWebView *)webView{

[self addJavaScript];
[webView stringByEvaluatingJavaScriptFromString:@"setImage();"];

// new for memory cleaning
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}


- (void)addJavaScript {

NSString *clickGirl =
@"function setImage(){\
var imgs = document.getElementsByTagName(\"img\");\
for (var i=0;i<imgs.length-1;i++){\
imgs[i].setAttribute(\"onClick\",\"imageClick(\"+i+\")\");\
}\
}\
function imageClick(i){\
var rect = getImageRect(i);\
var imgs = document.getElementsByTagName(\"img\");\
var src = imgs[i].src;\
var url=\"clickgirl::\"+src+\"::\"+rect;\
document.location = url;\
}\
function getImageRect(i){\
var imgs = document.getElementsByTagName(\"img\");\
var rect;\
rect = imgs[i].getBoundingClientRect().left+\"::\";\
rect = rect+imgs[i].getBoundingClientRect().top+\"::\";\
rect = rect+imgs[i].width+\"::\";\
rect = rect+imgs[i].height;\
return rect;\
}\
";
[_webView stringByEvaluatingJavaScriptFromString:clickGirl];

}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest
                                                             *)request navigationType:(UIWebViewNavigationType)navigationType{

NSString *requestString = [[request URL] absoluteString];
NSArray *components = [requestString componentsSeparatedByString:@"::"];
if ([components[0] isEqualToString:@"clickgirl"]) {
    NSString * imgUrl = components[1];
    NSString *bodyWidth= [webView stringByEvaluatingJavaScriptFromString: @"document.body.scrollWidth"];
    int widthOfBody = [bodyWidth intValue];
    CGFloat initialScale = webView.frame.size.width/widthOfBody;
    CGRect frame = CGRectMake([components[2] floatValue] *initialScale,([components[3] floatValue]) * initialScale +64, [components[4] floatValue] *initialScale , [components[5] floatValue] *initialScale);
    NSString *fileName = [RNCachingURLProtocol cachePathForURLString:imgUrl];
    RNCachedData *memoryCache = [NSKeyedUnarchiver unarchiveObjectWithFile:fileName];
    UIImageView * imageView = [[UIImageView alloc] initWithFrame:frame];
    if (memoryCache!=nil) {
        imageView.image = [UIImage imageWithData:memoryCache.data];
      // 获取了图片,你想干啥干啥
    }else{
        //基本用不到
        [imageView sd_setImageWithURL:[NSURL URLWithString:imgUrl] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {

        }];
    }

}
    return YES;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值