Files
knowledge-kit/Chapter1 - iOS/1.8.md
2020-04-06 22:35:27 +08:00

142 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 教你实现微信公众号效果:长按图片保存到相册
> 不知道各位对于这个需求要如何解决?
>
> 可能有些人会想到js与原生交互js监听图片点击事件然后将图片的url传递给原生App端然后原生App将图片保存到相册这样子麻烦吗超麻烦。1、js监听图片长按事件2、js将图片url传递给原生3、原生通过图片的url生成UIImage4、保存UIImage到系统相册巨麻烦啊大哥我很懒的好不好
#### 那么问题跑出来了,怎么办最简单?
* 鉴于个人道行尚浅,我就将自己的想法说出来
* 有个js的api`Document.elementFromPoint()`
> The`elementFromPoint()`method of the[`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document)interface 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()](https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint)
附上Demo[Demo](https://github.com/FantasticLBP/BlogDemos)