iOS UIWebView仿微信H5页面实现长按保存图片功能

时间:2022-07-09 10:22:29

iOS UIWebView仿微信H5页面实现长按保存图片功能

拿到需求之后分析了一下,其实主要功能点就是如何才能通过手指按压位置获取到相应的图片资源。是不是很抓狂,如果考虑到设备适配,谁知道手指按在什么地方了。

直接google查到了下面的这两行代码,然后跑到H5大哥那请教,给我实际演示了一下,发现能够完美解决上面的问题。

NSString *imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", touchPoint.x, touchPoint.y];
NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:imgURL];

整篇文章的精髓就全在上面的那两行代码里了,接下来我就把完整的实现代码放上来。

首先是给UiWebView加一个长按手势。

UILongPressGestureRecognizer* longPressed = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
longPressed.delegate = self;
[self.webView addGestureRecognizer:longPressed];

接着在手势响应方法里面实现相应的获取图片地址的方法,并弹出SheetView。这里需要注意的是一定要判断手势的state属性,想知道后果的同学可以注掉判断代码自己尝试一下。另外就是如果手指长按位置是非图片的话,urlToSave是一个nil值。

- (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;
}

[self showImageOptionsWithUrl:urlToSave];
}

接下来的方法是调用一个自己封装好的SheetVIew,大家完全可以跳过,列出来只是为了不破坏代码的连贯性。

- (void)showImageOptionsWithUrl:(NSString *)imageUrl
{
RAActionCustomButton *saveBtn = [[RAActionCustomButton alloc] init];
saveBtn.type = kRAActionCustomButtonTypeSheetWhite;
[saveBtn setTitle:@"保存图片" forState:UIControlStateNormal];
saveBtn.touchUpInsideBlock = ^(RAActionCustomButton *btn){
[self saveImageToDiskWithUrl:imageUrl];
};

RAActionCustomButton *cancelBtn = [[RAActionCustomButton alloc] init];
cancelBtn.type = kRAActionCustomButtonTypeSheetWhite;
[cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
cancelBtn.touchUpInsideBlock = ^(RAActionCustomButton *btn){

};

RAActionSheet *sheet = [[RAActionSheet alloc] init];
sheet.actionBtns = @[ saveBtn, cancelBtn];
[sheet show];
}

最后就是请求图片并保存到相册的方法。这里需要注意一下cachePolicy这个参数,当前选择的参数含义是只有在cache中不存在data时才从原始地址下载。在实现过程中大家可以根据实际的功能需求来选择不同的参数。

- (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(image:didFinishSavingWithError:contextInfo:), NULL);
});
}];

[task resume];
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
[[RAProgressHUD sharedHUD] showErrorWithMessage:@"保存失败"];
}else{
[[RAProgressHUD sharedHUD] showSuccessWithMessage:@"保存成功"];
}
}
文章参考来源:简书作者:Two_Seven

iOS中UIWebView的使用详解

一、初始化与三种加载方式

UIWebView继承与UIView,因此,其初始化方法和一般的view一样,通过alloc和init进行初始化,其加载数据的方式有三种:

第一种:


- (void)loadRequest:(NSURLRequest *)request;

这是加载网页最常用的一种方式,通过一个网页URL来进行加载,这个URL可以是远程的也可以是本地的,例如我加载百度的主页:

    UIWebView * view = [[UIWebView alloc]initWithFrame:self.view.frame];
[view loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]
];
[self.view addSubview:view];

会得到如下的效果:
iOS UIWebView仿微信H5页面实现长按保存图片功能

第二种:


- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL;

这个方法需要将httml文件读取为字符串,其中baseURL是我们自己设置的一个路径,用于寻找html文件中引用的图片等素材。

第三种:


- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL;

这个方式使用的比较少,但也更加*,其中data是文件数据,MIMEType是文件类型,textEncodingName是编码类型,baseURL是素材资源路径。

二、一些常用的属性和变量


@property (nonatomic, assign) id <UIWebViewDelegate> delegate;

设置webView的代理

@property (nonatomic, readonly, retain) UIScrollView *scrollView;

内置的scrollView

@property (nonatomic, readonly, retain) NSURLRequest *request;

URL请求

- (void)reload;

重新加载数据

- (void)stopLoading;

停止加载数据

- (void)goBack;

返回上一级

- (void)goForward;

跳转下一级


@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;

获取能否返回上一级

@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;

获取能否跳转下一级

@property (nonatomic, readonly, getter=isLoading) BOOL loading;

获取是否正在加载数据

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

通过javaScript操作web数据


@property (nonatomic) BOOL scalesPageToFit;

设置是否缩放到适合屏幕大小


@property (nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);

设置某些数据变为链接形式,这个枚举可以设置如电话号,地址,邮箱等转化为链接

@property (nonatomic) BOOL allowsInlineMediaPlayback NS_AVAILABLE_IOS(4_0);

设置是否使用内联播放器播放视频

@property (nonatomic) BOOL mediaPlaybackRequiresUserAction NS_AVAILABLE_IOS(4_0);

设置视频是否自动播放

@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay NS_AVAILABLE_IOS(5_0);

设置音频播放是否支持ari play功能

@property (nonatomic) BOOL suppressesIncrementalRendering NS_AVAILABLE_IOS(6_0);

设置是否将数据加载如内存后渲染界面


@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS(6_0);

设置用户交互模式

三、iOS7中的一些新特性


下面这些属性是iOS7之后才有的,通过他们可以设置更加有趣的web体验

@property (nonatomic) UIWebPaginationMode paginationMode NS_AVAILABLE_IOS(7_0);

这个属性用来设置一种模式,当网页的大小超出view时,将网页以翻页的效果展示,枚举如下:

typedef NS_ENUM(NSInteger, UIWebPaginationMode) {
UIWebPaginationModeUnpaginated,//不使用翻页效果
UIWebPaginationModeLeftToRight,//将网页超出部分分页,从左向右进行翻页
UIWebPaginationModeTopToBottom,//将网页超出部分分页,从上向下进行翻页
UIWebPaginationModeBottomToTop,//将网页超出部分分页,从下向上进行翻页
UIWebPaginationModeRightToLeft//将网页超出部分分页,从右向左进行翻页
};
@property (nonatomic) CGFloat pageLength NS_AVAILABLE_IOS(7_0);

设置每一页的长度

@property (nonatomic) CGFloat gapBetweenPages NS_AVAILABLE_IOS(7_0);

设置每一页的间距

@property (nonatomic, readonly) NSUInteger pageCount NS_AVAILABLE_IOS(7_0);

获取分页数

四、webView协议中的方法


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

准备加载内容时调用的方法,通过返回值来进行是否加载的设置

- (void)webViewDidStartLoad:(UIWebView *)webView;

开始加载时调用的方法

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

结束加载时调用的方法

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;

加载失败时调用的方法