長按UIWebView上的圖片儲存到相簿

杭城小劉發表於2017-08-02

不知道各位對於這個需求要如何解決?

可能有些人會想到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

相關文章