1.网页监听APP返回键(原生goback)
假设需求:当APP点击原生导航栏左上角返回键时,APP并不返回上级VC,而是让UIWebView返回上级页面。
1.1首先
新建CMWebViewController,让其继承UIViewController,即:
- CMWebViewController.h中有:
@interface CMWebViewController : UIViewController
1.2 其次
建议基于UIViewController自建一个BackButtonHandler的分类,如UIViewController+BackButtonHandler.h
和UIViewController+BackButtonHandler.m
。
- UIViewController+BackButtonHandler.h
#import <UIKit/UIKit.h>
@protocol BackButtonHandlerProtocol <NSObject>
@optional
-(BOOL)navigationShouldPopOnBackButton;
@end
@interface UIViewController (BackButtonHandler) <BackButtonHandlerProtocol>
@end
- UIViewController+BackButtonHandler.m
#import "UIViewController+BackButtonHandler.h"
@implementation UIViewController (BackButtonHandler)
@end
@implementation UINavigationController (ShouldPopOnBackButton)
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if([self.viewControllers count] < [navigationBar.items count]) {
return YES;
}
BOOL shouldPop = YES;
UIViewController* vc = [self topViewController];
if([vc respondsToSelector:@selector(navigationShouldPopOnBackButton)]) {
shouldPop = [vc navigationShouldPopOnBackButton];
}
if(shouldPop) {
dispatch_async(dispatch_get_main_queue(), ^{
[self popViewControllerAnimated:YES];
});
} else {
// Workaround for iOS7.1. Thanks to @boliva - http://stackoverflow.com/posts/comments/34452906
for(UIView *subview in [navigationBar subviews]) {
if(0. < subview.alpha && subview.alpha < 1.) {
[UIView animateWithDuration:.25 animations:^{
subview.alpha = 1.;
}];
}
}
}
return NO;
}
3.最后
在实现文件CMWebViewController.m
导入如上分类,并实现分类中BackButtonHandlerProtocol
协议的navigationShouldPopOnBackButton
方法。
- CMWebViewController.m
#import "CMWebViewController.h"
#import "UIViewController+BackButtonHandler.h"
@interface CMWebViewController ()<UIWebViewDelegate,JSObjcDelegate>
- (BOOL)navigationShouldPopOnBackButton
{
if ([_webView canGoBack]) {
[_webView goBack];
return NO;
}
return YES;
}
2.网页监听APP返回键(OC调用JS)
假设需求:APP隐藏原生导航栏,相当于网页全屏了,当在APP中点击网页端的左上角返回键时,APP退出UIWebView并返回上级VC页面。
2.1 iOS端
CMWebViewController实现文件代码
- 导入头文件
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JSObjcDelegate <JSExport>
//iosDelegate对象调用的JavaScript方法,必须声明!!!
- (void)getCall;
@end
- 代理及属性
@interface OpenHelpWebViewController ()<JSObjcDelegate>
@property (nonatomic, strong) JSContext *jsContext;
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
- 设置JS-OC交互对象
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// 设置javaScriptContext上下文
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 将iosDelegate对象指向自身
self.jsContext[@"iosDelegate"] = self;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
}
- iosDelegate对象方法(恭候JS调用)
- (void)getCall{
NSLog(@"call");
// 之后在回调JavaScript的方法Callback把内容传出去
dispatch_async(dispatch_get_main_queue(), ^{
//APP返回上级页面动作
[self.navigationController popViewControllerAnimated:YES];
});
}
2.2 H5/JS端
- H5关键部分:布局元素ID
<header class="header test">
<span>
![](./testFile/backIcon.png)
</span>
<h2 class="txt_cen">网页端标题</h2>
<div></div>
</header>
- JS关键部分:调用OC方法
<script type="text/javascript">
$("#backId").click(function(){
var flag = getTheFlagString("flag");
if(flag == "h5"){
history.go(-1);
}else if(android){
window.androidDelegate.getCall();
}else if(ios){
window.iosDelegate.getCall();
}
});
</script>