长按UIWebView上的图片保存到相册

作者: 杭城小刘 | 来源:发表于2017-08-02 17:56 被阅读309次

长按UIWebView上的图片保存到相册

不知道各位对于这个需求要如何解决?

可能有些人会想到js与原生交互,js监听图片点击事件,然后将图片的url传递给原生App端,然后原生App将图片保存到相册,这样子麻烦吗?超麻烦。(1)、js监听图片长按事件;(2)、js将图片url传递给原生;(3)、原生通过图片的url生成UIImage;(4)、保存UIImage到系统相册,巨麻烦啊,大哥,我很懒的好不好

那么问题跑出来了,怎么办最简单?

  • 鉴于个人道行尚浅,我就将自己的想法说出来

  • 有个js的api:Document.elementFromPoint()

TheelementFromPoint()method of theDocumentinterface returns the topmost element at the specified coordinates.

所以根据这个提示,我们完全可以只在App原生端做一些代码开发,实现这个需求

开发步骤

*给UIWebView添加长按手势
*监听手势动作,拿到坐标点(x,y)
*UIWebView注入js:Document.elementFromPoint(x,y).src拿到img标签的src
*判断拿到的src是否有值,有值则代表点击的网页上的img标签,此时弹出对话框,是否保存到相册。如果src为空,则代表点击网页上的非img标签,则不需要弹出对话框。
*拿到图片的url,生成UIImage。再将图片保存到相册

有巨坑

  • 长按手势事件不能每次都响应,据我猜测UIWebView本身就有很多事件,所以实现下UIGestureRecognizerDelegate代理方法。长按手势准确率100%
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}
//
//  ViewController.m
//  WebView长按图片保存到相册
//
//  Created by 杭城小刘 on 2017/8/2.
//  Copyright © 2017年 杭城小刘. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()<UIGestureRecognizerDelegate,NSURLSessionDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;

@end

@implementation ViewController

#pragma mark -- life cycle
- (void)viewDidLoad{
    [super viewDidLoad];
    
    NSString *htmlURL = [[NSBundle mainBundle] pathForResource:@"saveImage" ofType:@"html"];
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlURL]]];
    //给UIWebView添加手势
    UILongPressGestureRecognizer* longPressed = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
    longPressed.delegate = self;
    [self.webView addGestureRecognizer:longPressed];
}

#pragma mark -- UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    UIActivityTypeAddToReadingList
    return YES;
}

- (void)longPressed:(UILongPressGestureRecognizer*)recognizer{
    if (recognizer.state != UIGestureRecognizerStateBegan) {
        return;
    }
    CGPoint touchPoint = [recognizer locationInView:self.webView];
    NSString *imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];
    NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:imgURL];
    if (urlToSave.length == 0) {
        return;
    }
    
    UIAlertController *alertVC =  [UIAlertController alertControllerWithTitle:@"大宝贝儿" message:@"你真的要保存图片到相册吗?" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"真的啊" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self saveImageToDiskWithUrl:urlToSave];
    }];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"大哥,我点错了,不好意思" style:UIAlertActionStyleDefault handler:nil];
    [alertVC addAction:okAction];
    [alertVC addAction:cancelAction];
    [self presentViewController:alertVC animated:YES completion:nil];
}

#pragma mark - private method
- (void)saveImageToDiskWithUrl:(NSString *)imageUrl{
    NSURL *url = [NSURL URLWithString:imageUrl];
    
    NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue new]];
    
    NSURLRequest *imgRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
    
    NSURLSessionDownloadTask  *task = [session downloadTaskWithRequest:imgRequest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            return ;
        }
        NSData * imageData = [NSData dataWithContentsOfURL:location];
        dispatch_async(dispatch_get_main_queue(), ^{
            
            UIImage * image = [UIImage imageWithData:imageData];
            UIImageWriteToSavedPhotosAlbum(image, self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), NULL);
        });
    }];
    [task resume];
}

#pragma mark 保存图片后的回调
- (void)imageSavedToPhotosAlbum:(UIImage*)image didFinishSavingWithError:  (NSError*)error contextInfo:(id)contextInfo{
    NSString*message =@"嘿嘿";
    if(!error) {
        UIAlertController *alertControl = [UIAlertController alertControllerWithTitle:@"提示" message:@"成功保存到相册" preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:nil];
        [alertControl addAction:action];
        [self presentViewController:alertControl animated:YES completion:nil];
    }else{
        message = [error description];
        UIAlertController *alertControl = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
        [alertControl addAction:action];
        [self presentViewController:alertControl animated:YES completion:nil];
    }
}

@end

附上关键的js官方文档:Document.elementFromPoint()

附上Demo:Demo

相关文章

网友评论

  • 一夕007:这个对于图片的捕捉没有js 准确 ,测试使用注入js和你的方法对比 ,js注入可以对边角处理的较准确,但是你的方法 会出现点在图片外就弹窗提示 ,点击图片边缘一些缺不会弹窗提示
    杭城小刘:@一夕007 Demo地址:https://github.com/FantasticLBP/BlogDemos
    杭城小刘:@一夕007 不知道你有没有看我的Html样式,你说的这种情况不存在的。我在github上放了一个Demo,你可以下载下来看看,我给图片加了背景颜色,你可以看看哪些范围是图片,这个完全可以达到微信公众号网页上长按保存图片的效果。
  • 陈逸辰:有个缺点,原生加了长按监听,js就没办法捕捉这个动作了
    杭城小刘:@陈逸辰 这个是不会冲突的啊,事件的处理层级不一样,原生端处理自己的长按手势,js如果监听的话也在js那边处理自己的长按手势,完全不会影响的
    陈逸辰:@杭城小刘 比如h5代码层级自己要识别长按手势
    杭城小刘:长按监听为什么没办法捕捉???js不需要捕捉啊,原生监听长按手势,然后拿到(x,y).,然后webview通过document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y]拿到图片的src。不明白你说的“js就没办法捕捉这个动作了”是什么意思??

本文标题:长按UIWebView上的图片保存到相册

本文链接:https://www.haomeiwen.com/subject/mtjylxtx.html