IOS开发入门iOS用WKWebView与JS交互获取系统图片及WKWebView的Alert,Confirm,TextInput的监听代理方法使用,屏蔽Web
白羽 2019-07-10 来源 :网络 阅读 4134 评论 0

摘要:本文将带你了解IOS开发入门iOS用WKWebView与JS交互获取系统图片及WKWebView的Alert,Confirm,TextInput的监听代理方法使用,屏蔽WebView的可选菜单,希望本文对大家学IOS有所帮助。

    本文将带你了解IOS开发入门iOS用WKWebView与JS交互获取系统图片及WKWebView的Alert,Confirm,TextInput的监听代理方法使用,屏蔽WebView的可选菜单,希望本文对大家学IOS有所帮助。

IOS开发入门iOS用WKWebView与JS交互获取系统图片及WKWebView的Alert,Confirm,TextInput的监听代理方法使用,屏蔽Web

最近做一个项目,开始是使用WebView与JS交互的,由于内存管理方面WebView欠佳。WKWebVIew的内存线程管理好,所以选择使用   WKWebVIew(使用WKWebView 的缺点在于,这个控件加载的H5页面不支持ajax请求,所以需要自己把网络请求在OC上实现)。
    一、首先说下应该注意的问题:
    1.要获取拍照或相册的图片,如果是iOS 10系统,需要设置访问权限(在 Info-plist 中设置)
    相机权限: Privacy - Camera Usage Description 是否允许此App使用你的相机?
    相册权限: Privacy - Photo Library Usage Description 是否允许此App访问你的媒体资料库?
    2.WebView和WKWebView和JS互调的方法和使用的传参类型不同
    WebView 使用   (window.iosModel.getImage(JSON.stringify(parameter));//JSON.stringify(参数字符串)   这个方法是 把字符串转换成json字符串 parameter是参数字符串
    )传值给 OC
    WKWebView 使用   (window.webkit.messageHandlers.iosModel.postMessage(parameter))
    3.需要特别注意的是:WKWebView 不执行JS写的 ajax请求(WKWebView 可能由于基于 WebKit,并不会执行 C socket   相关的函数对 HTTP 请求进行处理)如果有网络请求,需要自己用OC实现
    4.使用的时候不要忘记挂上使用到的代理,和导入代理
     
@interface ViewController () <wkscriptmessagehandler,   uiimagepickercontrollerdelegate=""></wkscriptmessagehandler,>
    5.屏蔽WebView的可选菜单(即不会出现拷贝、全选等弹出菜单)在加载完成后的代理中执行以下两段JS
     
    // 导航完成时,会回调(也就是页面载入完成了)- (void)webView:(WKWebView *)webView   didFinishNavigation:(null_unspecified WKNavigation *)navigation   {    NSLog(@"66===%s",   __FUNCTION__);    // 禁用选中效果    [self.webView   evaluateJavaScript:@"document.documentElement.style.webkitUserSelect='none'"   completionHandler:nil];    [self.webView   evaluateJavaScript:@"document.documentElement.style.webkitTouchCallout='none'"   completionHandler:nil];}
     
    二、代码:
    
   
    JS与iOS交互
    JS页面获取iOS系统图片
   
    IOSImage()" style="width: 50%;height: 5%;"   type="button" value="打开相机获取图片" />
   
   
   
    <script>
     var getIOSImage = function(){
     var parameter = {'title':'JS调OC','describe':'这里就是JS传给OC的参数'};
     // 在下面这里实现js 调用系统原生api iosDelegate
                      //JSON.stringify(参数字符串) 这个方法是 把字符串转换成json字符串
     window.iosDelegate.getImage(JSON.stringify(parameter));// 实现数据的 json   格式字符串
     }
            // 这里是 iOS调用js的方法
            function   setImageWithPath(arguments){
                  document.getElementById('changeImage').src =   arguments['imagePath'];
                  document.getElementById('iosParame').innerHTML =   arguments['iosContent'];
            }
     </script>
    ?1 
    #import "ViewController.h" #import  #import    #import "SaveImage_Util.h" @interface ViewController ()  @property (nonatomic, strong) WKWebView   *webView; @property (nonatomic, strong) UIProgressView *progressView; @end   @implementation ViewController { int indextNumb;// 交替图片名字 UIImage   *getImage;//获取的图片 } - (void)viewDidLoad { [super viewDidLoad];   self.edgesForExtendedLayout = UIRectEdgeNone; self.automaticallyAdjustsScrollViewInsets   = NO; WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];   // 设置偏好设置 config.preferences = [[WKPreferences alloc] init]; // 默认为0   config.preferences.minimumFontSize = 10; // 默认认为YES config.preferences.javaScriptEnabled   = YES; // 在iOS上默认为NO,表示不能自动通过窗口打开   config.preferences.javaScriptCanOpenWindowsAutomatically = NO; // web内容处理池   config.processPool = [[WKProcessPool alloc] init]; // 通过JS与webview内容交互   config.userContentController = [[WKUserContentController alloc] init]; //   注入JS对象名称AppModel,当JS通过AppModel来调用时, // 我们可以在WKScriptMessageHandler代理中接收到   [config.userContentController addScriptMessageHandler:self   name:@"iosModel"]; //通过默认的构造器来创建对象 self.webView = [[WKWebView   alloc] initWithFrame:self.view.bounds configuration:config]; // 导航代理   self.webView.navigationDelegate = self; // 与webview UI交互代理   self.webView.UIDelegate = self; NSURL *path = [[NSBundle mainBundle]   URLForResource:@"testJS" withExtension:@"html"];   [self.webView loadRequest:[NSURLRequest requestWithURL:path]]; [self.view   addSubview:self.webView]; // 添加KVO监听 [self.webView addObserver:self   forKeyPath:@"loading" options:NSKeyValueObservingOptionNew   context:nil]; [self.webView addObserver:self forKeyPath:@"title"   options:NSKeyValueObservingOptionNew context:nil]; [self.webView   addObserver:self forKeyPath:@"estimatedProgress"   options:NSKeyValueObservingOptionNew context:nil]; // 添加进入条 self.progressView   = [[UIProgressView alloc] init]; self.progressView.frame = self.view.bounds;   [self.view addSubview:self.progressView]; self.progressView.backgroundColor =   [UIColor blackColor]; self.navigationItem.leftBarButtonItem =   [[UIBarButtonItem alloc] initWithTitle:@"后退"   style:UIBarButtonItemStyleDone target:self action:@selector(goback)];   self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]   initWithTitle:@"前进" style:UIBarButtonItemStyleDone target:self   action:@selector(gofarward)]; } - (void)goback { if ([self.webView canGoBack])   { [self.webView goBack]; } } - (void)gofarward { if ([self.webView   canGoForward]) { [self.webView goForward]; } } #pragma mark -   WKScriptMessageHandler // 通过这个方法获取 JS传来的json字符串 -   (void)userContentController:(WKUserContentController *)userContentController   didReceiveScriptMessage:(WKScriptMessage *)message { if ([message.name   isEqualToString:@"iosModel"]) { // 打印所传过来的参数,只支持NSNumber, NSString,   NSDate, NSArray, // NSDictionary, and NSNull类型 NSLog(@"JS传来的json字符串 :   %@", message.body); NSDictionary *jsDictionary = message.body; if   ([jsDictionary[@"means"] isEqualToString:@"获取系统图片"]) {   [self beginOpenPhoto]; } } } #pragma mark - KVO -   (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary   *)change context:(void *)context { if ([keyPath   isEqualToString:@"loading"]) { NSLog(@"loading"); } else   if ([keyPath isEqualToString:@"title"]) { self.title =   self.webView.title; } else if ([keyPath isEqualToString:@"estimatedProgress"])   { NSLog(@"progress: %f", self.webView.estimatedProgress);   self.progressView.progress = self.webView.estimatedProgress; } if   (!self.webView.loading) { [UIView animateWithDuration:0.5 animations:^{   self.progressView.alpha = 0; }]; } } #pragma mark - WKNavigationDelegate //   请求开始前,会先调用此代理方法 // 与UIWebView的 // - (BOOL)webView:(UIWebView *)webView //   shouldStartLoadWithRequest:(NSURLRequest *)request //   navigationType:(UIWebViewNavigationType)navigationType; // 类型,在请求先判断能不能跳转(请求)   - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:   (WKNavigationAction *)navigationAction decisionHandler:(void   (^)(WKNavigationActionPolicy))decisionHandler { NSString *hostname =   navigationAction.request.URL.host.lowercaseString; if   (navigationAction.navigationType == WKNavigationTypeLinkActivated &&   ![hostname containsString:@".lanou.com"]) { // 对于跨域,需要手动跳转,   用系统浏览器(Safari)打开 [[UIApplication sharedApplication]   openURL:navigationAction.request.URL]; // 不允许web内跳转   decisionHandler(WKNavigationActionPolicyCancel); } else {   self.progressView.alpha = 1.0;   decisionHandler(WKNavigationActionPolicyAllow); } } // 在响应完成时,会回调此方法 //   如果设置为不允许响应,web内容就不会传过来 - (void)webView:(WKWebView *)webView   decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse   decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {   decisionHandler(WKNavigationResponsePolicyAllow); } // 开始导航跳转时会回调 -   (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified   WKNavigation *)navigation { } // 接收到重定向时会回调 - (void)webView:(WKWebView   *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified   WKNavigation *)navigation { } // 导航失败时会回调 - (void)webView:(WKWebView   *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation   *)navigation withError:(NSError *)error { } // 页面内容到达main frame时回调 -   (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified   WKNavigation *)navigation { } // 导航完成时,会回调(也就是页面载入完成了) -   (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified   WKNavigation *)navigation { NSLog(@"66===%s", __FUNCTION__); //   禁用选中效果 [self.webView   evaluateJavaScript:@"document.documentElement.style.webkitUserSelect='none'"   completionHandler:nil]; [self.webView   evaluateJavaScript:@"document.documentElement.style.webkitTouchCallout='none'"   completionHandler:nil]; } // 导航失败时会回调 - (void)webView:(WKWebView *)webView   didFailNavigation: (null_unspecified WKNavigation *)navigation   withError:(NSError *)error { } /* 对于HTTPS的都会触发此代理,如果不要求验证,传默认就行   如果需要证书验证,与使用AFN进行HTTPS证书验证是一样的 */ - (void)webView:(WKWebView *)webView   didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge   completionHandler: (void (^)(NSURLSessionAuthChallengeDisposition   disposition, NSURLCredential *__nullable credential))completionHandler {   completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } //   9.0才能使用,web内容处理中断时会触发 /* - (void)webViewWebContentProcessDidTerminate:(WKWebView   *)webView { } */ #pragma mark - WKUIDelegate -   (void)webViewDidClose:(WKWebView *)webView { } /*   在JS端调用alert函数时,会触发此代理方法。JS端调用alert时所传的数据可以通过message拿到   在原生得到结果后,需要回调JS,是通过completionHandler回调 */ - (void)webView:(WKWebView   *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message   initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void   (^)(void))completionHandler { UIAlertController *alert = [UIAlertController   alertControllerWithTitle:@"alert" message:message preferredStyle:UIAlertControllerStyleAlert];   [alert addAction:[UIAlertAction actionWithTitle:@"确定"   style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {   completionHandler(); }]]; [self presentViewController:alert animated:YES completion:NULL];   NSLog(@"%@", message); } // JS端调用confirm函数时,会触发此方法 //   通过message可以拿到JS端所传的数据 // 在iOS端显示原生alert得到YES/NO后 // 通过completionHandler回调给JS端   - (void)webView:(WKWebView *)webView   runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo   *)frame completionHandler:(void (^)(BOOL result))completionHandler {   UIAlertController *alert = [UIAlertController   alertControllerWithTitle:@"confirm" message:message   preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction   actionWithTitle:@"确定" style:UIAlertActionStyleDefault   handler:^(UIAlertAction * _Nonnull action){ completionHandler(YES); }]];   [alert addAction:[UIAlertAction actionWithTitle:@"取消"   style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {   completionHandler(NO); }]]; [self presentViewController:alert animated:YES   completion:NULL]; NSLog(@"%@", message); } // JS端调用prompt函数时,会触发此方法   // 要求输入一段文本 // 在原生输入得到文本内容后,通过completionHandler回调给JS -   (void)webView:(WKWebView *)webView   runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt   defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo   *)frame completionHandler:(void (^)(NSString * __nullable   result))completionHandler { UIAlertController *alert = [UIAlertController   alertControllerWithTitle:prompt message:defaultText   preferredStyle:UIAlertControllerStyleAlert]; [alert   addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {   textField.textColor = [UIColor redColor]; }]; [alert addAction:[UIAlertAction   actionWithTitle:@"确定" style:UIAlertActionStyleDefault   handler:^(UIAlertAction * _Nonnull action) {   completionHandler([[alert.textFields lastObject] text]); }]]; [self   presentViewController:alert animated:YES completion:NULL]; } // 获取图片 -   (void)beginOpenPhoto { // 主队列 异步打开相机   dispatch_async(dispatch_get_main_queue(), ^{ [self takePhoto]; }); } #pragma   mark 取消选择照片代理方法 -   (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker   dismissViewControllerAnimated:YES completion:nil]; } #pragma mark //打开本地照片 -   (void) localPhoto { UIImagePickerController *imagePicker =   [[UIImagePickerController alloc]init]; imagePicker.sourceType =   UIImagePickerControllerSourceTypePhotoLibrary; imagePicker.delegate = self;   [self presentViewController:imagePicker animated:YES completion:nil]; }   #pragma mark //打开相机拍照 - (void) takePhoto { UIImagePickerControllerSourceType   sourceType = UIImagePickerControllerSourceTypeCamera; if ([UIImagePickerController   isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {   UIImagePickerController *picker = [[UIImagePickerController alloc]init];   picker.delegate = self; picker.allowsEditing = YES; picker.sourceType =   sourceType; picker.modalTransitionStyle =   UIModalTransitionStyleCoverVertical; [self presentViewController:picker   animated:YES completion:nil]; } else { NSLog(@"模拟器中不能打开相机"); [self   localPhoto]; } } // 选择一张照片后进入这里 -   (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary   *)info { NSString *type = [info   objectForKey:UIImagePickerControllerMediaType]; // 当前选择的类型是照片 if ([type   isEqualToString:@"public.image"]) { // 获取照片 getImage = [info   objectForKey:@"UIImagePickerControllerOriginalImage"];   NSLog(@"===Decoded image size: %@",   NSStringFromCGSize(getImage.size)); // obtainImage 压缩图片 返回原尺寸 indextNumb =   indextNumb == 1?2:1; NSString *nameStr = [NSString   stringWithFormat:@"Varify%d.jpg",indextNumb]; [SaveImage_Util   saveImage:getImage ImageName:nameStr back:^(NSString *imagePath) {   dispatch_async(dispatch_get_main_queue(), ^{   NSLog(@"图片路径:%@",imagePath); /** * 这里是IOS 调 js 其中 setImageWithPath   就是js中的方法 setImageWithPath(),参数是字典 */ NSString *callJSString = [NSString   stringWithFormat:@"%@({\"imagePath\":\"%@\",\"iosContent\":\"获取图片成功,把系统获取的图片路径传给js   让html显示\"})",@"setImageWithPath",imagePath];   [self.webView evaluateJavaScript:callJSString completionHandler:^(id   resultObject, NSError * _Nullable error) { if (!error) { NSLog(@"OC调   JS成功"); } else { NSLog(@"OC调 JS 失败"); } }]; }); }]; [picker   dismissViewControllerAnimated:YES completion:nil]; } } @end
   
   
   
   
     

    下面是图片处理的 工具类
     
     
    //  SaveImage_Util.h//  JS和iOS交互////    Created by user on 16/10/14.//  Copyright © 2016年 user. All rights   reserved.// #import <foundation foundation.h="">#import   <uikit uikit.h="">@interface SaveImage_Util : NSObject#pragma   mark  保存图片到document+ (BOOL)saveImage:(UIImage *)saveImage   ImageName:(NSString *)imageName back:(void(^)(NSString   *imagePath))back; @end</uikit></foundation>
   
      //    SaveImage_Util.m//  JS和iOS交互////  Created by user on   16/10/14.//  Copyright © 2016年 user. All rights reserved.// #import   "SaveImage_Util.h" @implementation SaveImage_Util#pragma   mark  保存图片到document+ (BOOL)saveImage:(UIImage *)saveImage ImageName:(NSString   *)imageName back:(void(^)(NSString   *imagePath))back{    NSString *path = [SaveImage_Util   getImageDocumentFolderPath];    NSData *imageData =   UIImagePNGRepresentation(saveImage);    NSString   *documentsDirectory = [NSString stringWithFormat:@"%@/",   path];    // Now we get the full path to the   file    NSString *imageFile = [documentsDirectory   stringByAppendingPathComponent:imageName];    // and then   we write it out    NSFileManager *fileManager =   [NSFileManager   defaultManager];    //如果文件路径存在的话    BOOL   bRet = [fileManager fileExistsAtPath:imageFile];    if   (bRet)    {        //          NSLog(@"文件已存在");        if   ([fileManager removeItemAtPath:imageFile   error:nil])        {            //              NSLog(@"删除文件成功");            if   ([imageData writeToFile:imageFile   atomically:YES])            {                //                  NSLog(@"保存文件成功");                back(imageFile);            }        }        else        {                     }             }    else    {        if   (![imageData writeToFile:imageFile   atomically:NO])        {            [fileManager   createDirectoryAtPath:documentsDirectory withIntermediateDirectories:YES   attributes:nil   error:nil];            if   ([imageData writeToFile:imageFile   atomically:YES])            {                back(imageFile);            }        }        else        {            return   YES;        }             }    return   NO;}#pragma mark  从文档目录下获取Documents路径+ (NSString   *)getImageDocumentFolderPath{    NSString *patchDocument   = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,   YES) lastObject];    return [NSString   stringWithFormat:@"%@/Images", patchDocument];}@end
   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之IOS频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 1
看完这篇文章有何感觉?已经有2人表态,50%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程