一、iOS中的UIWebView
1、什么是UIWebView?
UIWebView是iOS内置的浏览器控件; UIWebView不但能加载远程的网页资源,还能加载绝大部分的常见文件html、pdf、doc、ppt、txt等。
如加载PPT:
NSURL *url = [NSURLfileURLWithPath:@"/Users/zhaoyongfei/Desktop/test.pptx"];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
加载远程网页:
NSURL *url = [[NSURL alloc] initWithString:@"https://baidu.com"];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
2、UIWebView的基本属性和方法使用
@property (nullable, nonatomic, assign) id delegate;
@property (nonatomic, readonly, strong) UIScrollView *scrollView NS_AVAILABLE_IOS(5_0);
- (void)loadRequest:(NSURLRequest *)request;
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;
- (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;
//webView调用JS方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
//默认值为NO,用户不可以放大或缩小页面;如果设置为YES,页面可以通过放大缩小去适应,用户也可以通过手势来放大和缩小
@property (nonatomic) BOOL scalesPageToFit;
__TVOS_PROHIBITED @protocol UIWebViewDelegate
//webView加载中的生命周期,以下方法按照顺序
//代理方法
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
/**返回YES,进行加载。通过UIWebViewNavigationType可以得到请求发起的原因
如果为webView添加了delegate对象并实现该接口,那么在webView加载任何一个frame之前都会delegate对象的该方法,该方法的返回值用以控制是否允许加载目标链接页面的内容,返回YES将直接加载内容,NO则反之。并且UIWebViewNavigationType枚举,定义了页面中用户行为的分类,包括;
UIWebViewNavigationTypeLinkClicked,0 用户触击了一个链接。
UIWebViewNavigationTypeFormSubmitted,1 用户提交了一个表单。
UIWebViewNavigationTypeBackForward,2, 用户触击前进或返回按钮。
UIWebViewNavigationTypeReload,3, 用户触击重新加载的按钮。
UIWebViewNavigationTypeFormResubmitted,4,用户重复提交表单
UIWebViewNavigationTypeOther,5, 发生其它行为。
*/
// NSLog(@"----request-------%@",request);
NSLog(@"----navigationType-------%ld",(long)navigationType);
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView{
//开始加载,可以加上风火轮(也叫菊花)
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//完成加载
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
//加载出错
}
二、UIWebView和JS的交互(JavaScriptCore框架)
JavaScriptCore框架其实就是基于webkit中以C/C++实现的JavaScriptCore的一个包装,提供了Objective-C的封装接口。
1、UIWebView调用JS
相当于给js发送一段字符串,然后程序会根据字符串去环境中寻找对应的方法并执行。
[self.webView stringByEvaluatingJavaScriptFromString:@"setDomineeringShare()"];
[self.webView stringByEvaluatingJavaScriptFromString:@"APPJsBridge.onFinish(@"",@"")"];
2、JS调用UIWebView
JSContext:js执行环境,包含了js执行时所需要的所有函数和对象;js执行时,会在执行环境搜索需要的函数然后执行,或者保存传入的变量或函数;
但是苹果并没有开放获取JSContext环境对象的方法,目前是通过KVC的方式获取JSContext环境对象:
JSContext *context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"APPJSBridge"] = self.bridge;//self.bridge对象里面是实现了和JS协商好的方法(如- (void)webClose方法等)
坑:页面跳转之后,JSContext发生了变化,于是再次利用JSContext setObject注册API的时候,前端的js接口已经调用了,此时前端就会报找不到对象的错误。
解决方法:
1.可以通过在js设置setTimeout来让任务放到执行队列的末端,先执行oc层的webVIewDidFinishLoad方法,待任务完成后再执行js中的异步代码; 或者JS设置一个监听监听OC是否加载完成,如果完成就调用方法。
2.用一个私有API,监听何时创建好jscontext,在这时候注入。这个方法很好,只是苹果不允许上架。
若想更深入了解参考:
https://www.jianshu.com/p/3f5dc8042dfc
3、项目中的使用
JS调用OC的方法;OC处理完事件后;返回给JS端处理结果(或者不返回处理结果)。
self.bridge类中实现- (void)commitJSBridge:(NSString *)msg方法;
//两端协议好msg的格式,项目中的格式协议好的参数格式
msg = JSBridge://bridge:756400989/jsBridgeTest?{"msg":"Hello JSBridge"}
URL:JSBridge://bridge:756400989/jsBridgeTest?{"msg":"Hello JSBridge"}
scheme : JSBridge;//判断是不是新的JS交互
host : bridge;
port : 756400989;//方法的唯一标示
path : showToast//OC方法名
{"msg":"Hello JSBridge"}//jsBridgeTest方法的参数
返回给JS端处理结果:
[self.webView stringByEvaluatingJavaScriptFromString:@"APPJsBridge.onFinish(markNumber,result)"];
三、iOS中的URL Scheme
苹果手机中的APP都有一个沙盒,APP之间是相互独立的,相互是不可以进行通信的,但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便app之间互相调用而设计的。URL Scheme必须能唯一标识一个APP,如果你设置的URL Scheme与别的APP的URL Scheme冲突时,你的APP不一定会被启动起来。
常用的scheme:
支付宝: alipay://
微信: weixin://
QQ: mqq://
腾讯微博: TencentWeibo://
淘宝: taobao://
微博: sinaweibo://
项目中的应用(推送,WebView,接口返回,跳转第三方应用)
无参数
APPJsBridge://video/download;
scheme : APPJsBridge;
host : video;
path : download
if ([url.scheme isEqualToString:@"APPJsBridge"]) {
if ([url.host isEqualToString:@"video"]){
if ([url.path isEqualToString:@"download"]){
//跳转到我的下载界面
带参数
(所有scheme参数都要urlEncode)
APPJsBridge://web?u=https%3A%2F%2Fwww.baidu.com%2F&ifShare=1&ifFull=0;
scheme : APPJsBridge;//判断是不是新的JS交互
host : web;
query : u=https%3A%2F%2Fwww.baidu.com%2F&ifShare=1&ifFull=0;
if ([url.scheme isEqualToString:@"APPJsBridge"]) {
if ([url.host isEqualToString:@"web"]){//跳转到H5界面
NSString *query = url.query;
NSMutableDictionary *canDic = [[ZYFHelpClass sharedInstance] shemeBecomeDictionary:query];
//最终拿到参数:
canDic = @{
@"u" : @"https://www.baidu.com",
@"ifShare" : @"1",
@"ifFull" : @"0"
};
//跳转到webView界面
参考: ([我叫纠结伦]https://www.jianshu.com/p/3f5dc8042dfc)