我们所要解决的问题如题目所示:ios中,长按Webview中的图片,将图片保存到本地相册。

解决方案:对load的html网页,执行js注入,通过在webview中执行js代码,来响应点击事件,通过js代码来模拟长按事件。发现图片的位置,获得图片的url链接,通过此链接获得图片,将此图片保存到本地相册。

js注入代码:

static NSString* const kTouchJavaScriptString=
@"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\";};";

这段js的作用主要用于响应touch事件,以及获得点击的坐标位置,
在webview加载完成之后,将此段js代码注入,源码如下:
-(void)webViewDidFinishLoad:(UIWebView *)webView {
    [self.getWebView stringByEvaluatingJavaScriptFromString:kTouchJavaScriptString];
}

js执行代码:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)_request navigationType:(UIWebViewNavigationType)navigationType {
    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"])
        {
            //NSLog(@"you are touching!");
            //NSTimeInterval delaytime = Delaytime;
            if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"start"])
            {
                /*
                 @需延时判断是否响应页面内的js...
                 */
                _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);
                
                NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).tagName", ptX, ptY];
                NSString * tagName = [self.getWebView stringByEvaluatingJavaScriptFromString:js];
                _imgURL = nil;
                if ([tagName isEqualToString:@"IMG"]) {
                    _imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", ptX, ptY];
                }
                if (_imgURL) {
                    _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleLongTouch) userInfo:nil repeats:NO];
                }
            }
            else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"move"])
            {
                //**如果touch动作是滑动,则取消hanleLongTouch动作**//
                _gesState = GESTURE_STATE_MOVE;
                NSLog(@"you are move");
                }
            }
            else if ([(NSString*)[components objectAtIndex:2]isEqualToString:@"end"]) {
                [_timer invalidate];
                _timer = nil;
                _gesState = GESTURE_STATE_END;
                NSLog(@"touch end");
            }
        }
        return NO;
    }
    return YES;
}

如果点击的是图片,并且按住的时间超过1s,执行handleLongTouch函数,处理图片的保存操作。
- (void)handleLongTouch {
    NSLog(@"%@", _imgURL);
    if (_imgURL && _gesState == GESTURE_STATE_START) {
        UIActionSheet* sheet = [UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"保存图片", nil];
        sheet.cancelButtonIndex = sheet.numberOfButtons - 1;
        [sheet showInView:[UIApplication sharedApplication].keyWindow];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (actionSheet.numberOfButtons - 1 == buttonIndex) {
        return;
    }
    NSString* title = [actionSheet buttonTitleAtIndex:buttonIndex];
    if ([title isEqualToString:@"保存图片"]) {
        if (_imgURL) {
            NSLog(@"imgurl = %@", _imgURL);
        }
        NSString *urlToSave = [self.getWebView stringByEvaluatingJavaScriptFromString:_imgURL];
        NSLog(@"image url=%@", urlToSave);
        
        NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlToSave];
        UIImage* image = [UIImage imageWithData:data];
        
        //UIImageWriteToSavedPhotosAlbum(image, nil, nil,nil);
        UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    }
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError*)error contextInfo:(void*)contextInfo
{
    if (error){
        NSLog(@"Error");
        [self showAlert:SNS_IMAGE_HINT_SAVE_FAILE];
    }else {
        NSLog(@"OK");
        [self showAlert:SNS_IMAGE_HINT_SAVE_SUCCE];
    }
}

iOS UIWebview 长按图片,保存到本地相册的更多相关文章

  1. React Native之图片保存到本地相册(ios android)

    React Native之图片保存到本地相册(ios android) 一,需求分析 1,react native保存网络图片到相册,iOS端可以用RN自带的CameraRoll完美解决,但是andr ...

  2. iOS-iOS调用相机调用相册【将图片保存到本地相册】

    设置头部代理 <UINavigationControllerDelegate, UIImagePickerControllerDelegate> 1.调用相机 检测前置摄像头是否可用 - ...

  3. iOS,长按图片保存实现方法,轻松搞定!

    1.添加手势识别: UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@s ...

  4. iOS开发小技巧--实现将图片保存到本地相册

    一.报错的代码 错误 -- out of bounds 超出界限的意思 *** Terminating app due to uncaught exception 'NSInvalidArgument ...

  5. ios 点击放大图片,保存至手机相册

    直接贴.m文件代码 #import "UIImageView+Scale.h" static CGRect oldframe; @implementation UIImageVie ...

  6. 微信小程序导出当前画布指定区域的内容并生成图片保存到本地相册(canvas)

    最近在学小程序,在把当前画布指定区域的内容导出并生成图片保存到本地这个知识点上踩坑了. 这里用到的方法是: wx.canvasToTempFilePath(),该方法作用是把当前画布指定区域的内容导出 ...

  7. iOS 将图片保存到本地

    //将图片保存到本地 + (void)SaveImageToLocal:(UIImage*)image Keys:(NSString*)key {     NSUserDefaults* prefer ...

  8. 微信小程序之base64图片如何预览与一键保存到本地相册?

    需求:由于后台服务器各方面的限制,现在服务器返回的图片是base64格式的,小程序端需要支持预览图片和多个图片一键下载功能 一.如何预览base64位图片? WXML页面:item.src的值是bas ...

  9. php 获取远程图片保存到本地

    php 获取远程图片保存到本地 使用两个函数 1.获取远程文件 2.把图片保存到本地 /** * 获取远程图片并把它保存到本地 * $url 是远程图片的完整URL地址,不能为空. */ functi ...

随机推荐

  1. ASP.NET Core设置URLs的几种方法

    前言 在使用ASP.NET Core 3.1开发时,需要配置服务器监听的端口和协议,官方帮助文档进行简单说明,文档中提到了4种指定URL的方法 设置ASPNETCORE_URLS 环境变量: 使用do ...

  2. TDSQL | 在整个技术解决方案中HTAP对应的混合交易以及分析系统应该如何实现?

    从主交易到传输,到插件式解决方案,每个厂商对HTAP的理解和实验方式都有自己的独到解法,在未来整个数据解决方案当中都会往HTAP中去牵引.那么在整个技术解决方案中HTAP对应的混合交易以及分析系统应该 ...

  3. 剑指 Offer 20. 表示数值的字符串

    方法:分为几个部分判断 DA[.B][E/eC] D 其中D表示前后的空格,需要处理,跳过即可 A可以带正负号 有符号数 B无符号数 C可以为有符号数(带+-号) 小数点.后面必须是无符号数或者没有 ...

  4. 动态sql & 抽取可重用sql

    抽取可重用的sql片段 抽取:<sql id="xx"></sql> 使用:<include refid="xx">< ...

  5. 力扣 - 剑指 Offer 59 - I. 滑动窗口的最大值

    题目 剑指 Offer 59 - I. 滑动窗口的最大值 思路1(单调队列) 使用单调(递减)队列,保持队列中的元素是递减顺序,队列头保存的是当前窗口中最大的元素 首先先模拟建立第一个窗口,同时获取第 ...

  6. 写给初学者的Linux errno 错误码机制

    不同于Java的异常处理机制, 当你使用C更多的接触到是基于错误码的异常机制, 简单来说就是当调用的函数发生异常时, 程序不会跳转到一个统一处理异常的地方, 取而代之的是返回一个整型错误码. 可能会有 ...

  7. 基于I2C的AHT20温湿度传感器的数据采集

    关于:IC( Inter-- Integrated Circuit)总线是一种由 PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.它是由数据线SDA和时钟SCL构成的串行总线,可 ...

  8. RDD的缓存

    RDD的缓存/持久化 缓存解决的问题 缓存解决什么问题?-解决的是热点数据频繁访问的效率问题 在Spark开发中某些RDD的计算或转换可能会比较耗费时间, 如果这些RDD后续还会频繁的被使用到,那么可 ...

  9. 题解 P6345 [CCO 2017]接雨滴

    解题思路 NOIP在即,感觉即将退役,或许是最后一篇题解了... 求水的体积不是特别好求,我们考虑求出 水+柱子 的体积最后再减去柱子的体积. 发现对于最高的柱子在中间的情况其实可以把最高柱子一侧的柱 ...

  10. [bzoj1858]序列操作

    考虑建立一棵线段树,维护:1.左端点的连续1和:2.右端点的连续1和:3.最长1的连续子序列:4.1的个数:5.将0和1交换后上面的四项:6.懒标记具体实现中,需要注意细节,可以看代码(比较短) 1 ...