iOS与web交互的那些事

时间:2023-03-08 15:34:05

  一转眼又是大半年过去了,除了上架了一款新应用外,也没什么进步。所以最近琢磨着搞点事情,不然我那本Java教程都快看完了。

  做为一名iOS高(la)阶(ji)法师,几乎所有的任务里,都会出现web这个从工会分配来的小(diao)助(che)手(wei)。这个助手身轻体盈易推倒,咳咳,易上手,可以简单快捷的帮助我完成任务,并且在我提交任务后,还可以随时修改我的任务内容,让我不得不对这个web重视起来。

  但是呢,小助手的缺点也是很明显的,迟钝。

  有次我要喝水,本可以用隔空取物瞬间拿到水,但是为了照顾一下工会的意思,就让助手去取,结果它慢吞吞磨磨唧唧半天才响应我。

  身为一个以快著名、以天下体验唯快不破为座右铭的我,怎么能忍受这么慢的助手,于是就回公会要求他们撤回web助手。

  结果当然是显而易见的。

  理由是,我的小助手可以随时修改任务内容,可以把任务里的水改成酒,甚至改成毒药,虽然指挥起来慢,但是可以骗过NPC。我可做不到,每次交任务时都要接受NPC的搜身,脱光光被看。

  现在每次出任务,都会带上小助手,所以我们的配合越来越默契,为了方便交流,我也看了看《web宠物交流手册》,觉得其实挺简单的,就是把我自己的意思,通过一款连接器转换成宠物能看得懂的意思,它就能乖乖的去做事情。等等,为什么web小助手突然变成了宠物。

  这个所谓的连接器,已经推出了二代产品,看来还挺畅销的。我从交流手册上选几段说明下宠物是怎么用的。

  第一章 第二节 -- "产品说明"

    本产品名为 ‘WKWebView’ 是使用web必备的工具,上一代产品为‘UIWebView’,新产品有以下优点:

      ·拥有更快的加载速度和性能,更低的内存占用。

      ·重构了委托协议,可以进行更精细化的管理和配置。

      ·支持更多的HTML5特性。(小助手宠物已经升级到第五代啦)

  第一章 第五节 -- "召唤"

    这一节主要介绍怎么利用WKWebView召唤宠物。以下咒语中,已包含和JS的配置,有做特殊说明。

 //初始化 webview 的设置。
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; //提供使用 JavaScript post 信息和注射 script 的方法。
WKUserContentController *userContentController = [[WKUserContentController alloc] init]; configuration.userContentController = self.userContentController; WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];

    就这么简单的几句咒语,就可以召唤属于自己的宠物小助手了,不过呢,我们希望它更加强大点,拥有更好的技能,那就继续念咒语。

 //设置委托,按需设置
webView.navigationDelegate = self;
webView.UIDelegate = self; //添加 加载进度,利用KVO
UIProgressView *progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, )]; //WK 有提供进度属性:estimatedProgress,监听方法就不累述了
[webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; [self.view addSubview:webView];
[self.view addSubview:progressView];

  第二章 第二节 -- "宠物语正向解析"

    如果各位大侠只是简单的把宠物召唤出来溜溜弯看看风景,就不需要增加以下咒语。这一节教学主要讲如何听懂宠物的语言,比如战斗时,宠物说‘进攻’,你听不懂还傻乎乎的站在原地可不行。确保能协同作战,相互照应。则需要这要的咒语:

 //添加要处理的JS方法
userContentController addScriptMessageHandler:self name:@"fire"]; //遵守协议 并实现委托方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
if ([@"fire" isEqualToString:message.name])
{
//TODO
}
}

    首先需要约定好方法名,战斗之前要和宠物讲,要让我进攻,就发出“&*……*&%&……(fire)”的惨叫,我就知道怎么做了。如果不按约定的套路叫,我就听不懂,不知道该做什么。无论添加多少个JS约定方法,都需要在这个委托方法中,对message.name进行区分判断然后分开处理。如果宠物在说fire的同时,把攻击坐标一起说了出来,那么,我们也要能拿到坐标才行,这个坐标,就在message.body里。对于这一套流程,我个人做了个小小封装处理,简化了注册和处理流程,这是后话,结尾再提。

    上面的咒语有个委托绑到了自己身上,这样会导致宠物无法召回,稍后会说到怎么处理避免这种情况。

  第二章 第三节 -- "宠物语逆向解析"

    上一节讲了怎么和宠物约定自己的动作事件,可以接收到宠物传过来的信息,对于这些信息,都需要提前约定好,而我们传递给宠物的命令信息,也需要约定。毕竟它也听不懂我们的语言。当我们需要撤退时,我们需要告诉它。当然,我们也可以把撤退坐标一起传过去。

 dispatch_async(dispatch_get_main_queue(), ^{
[webView evaluateJavaScript:@"retreat('14','15')" completionHandler:nil];
});

    在执行JS时最好在主线程进行。这样,我们就可以说“retreat(&……*&¥)”的话,它就知道该怎么做了。

  第三章 第一节 -- "管理"

    这一节只说WKNavigationDelegate的委托协议。我们要想更好的管理宠物的方方面面,需要监控它的一举一动。

// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; // 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation; // 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; // 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;

    除了上面几个常用的咒语,还有一些用来控制跳转的:

// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; // 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; // 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

    在这些方法里,做一些想做的事情,这样,宠物就可以最大化的发挥作用。或许,你需要注入一段JS自动填充web表单,那么就可以在页面加载完成的委托方法里,执行JS语句。

 [webView evaluateJavaScript:@"$('#user-name').val(\"李刚\");$('#user-id').val(\"330211299608164113\");$('#creditCard').val(\"320248476988112\");$('#cvn2Num').val(\"245\");$('#timeNum').val(\"0722\");$('#user-phone').val(\"13146853977\");$(\"#user-phone\").trigger(\"keyup\");" completionHandler:^(id _Nullable r, NSError * _Nullable error) {
if (error)
{
NSLog(@"[执行js错误]%@", error);
}
}];

    这样,我们就可以把它玩弄于股掌之间。随心所欲想做什么就做什么,哈哈哈,咳咳YY了一下。

  第三章 第三节 -- "使用"

    作为最终章节,这里说明如何在召唤宠物后,进行作战使用。在召唤出宠物,并做好相关的准备后,就可以让宠物陪同作战了。宠物作战方式可以分为两种,按需选择。第一种:远攻,也叫请求网络路径,第二种:近战,也叫加载本地文件。

 //远攻示意
NSURL *url = [NSURL URLWithString:URLString];
[webView loadRequest:[NSURLRequest requestWithURL:url]]; //近战示意
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; [webView loadHTMLString:[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil] baseURL:[[NSBundle mainBundle] bundleURL]];

    这样我们的宠物助手就派上用场啦。这里要注意的是,只有在iOS9及以上版本中,宠物才会这种方式的近战。

  说明手册大概就讲这么多吧,宠物其实很好调教的,只要用对地方,可以让自身更加强大。至于在使用中会遇到一些问题,并不影响我对它的喜爱。

  上文中提到宠物无法召回的情况,还有封装简化的处理,这里快速说明一下。使用 addScriptMessageHandler:name: 添加事件时,如果绑定的是自己,那么是无法彻底释放的,所以这里可以自己写个委托类,弱引用持有自己,实现 userContentController:didReceiveScriptMessage: 委托方法。然后在这个方法里进行处理。如果我们约定了很多的咒语,比如我,是个lv100的法师,宠物也肯定很强大啦,我们之间约定了好多战斗时用到的咒语,如果按照普通的方法在委托方法里写if一个一个判断message.name,那我的咒语符都写不下了。所以呢,我就简化了一下咒语。

 //数组里是自定义的model。里面存放我的语言和对应的宠物的语言
for (webJScriptItem *item in mothedList)
{
if ([item.jsMothodName isEqualToString:message.name])
{
SEL selector = NSSelectorFromString(item.ocMothodName); [self performSelector:selector withObject:message.body]; break;
}
}

  先到这里吧。

  懒得写了,确实好懒。