1、Web APP 在开发过程中不可避免的涉及到输入,所以今天来解决键盘弹起遮挡的问题,主要从iOS原生的方面来解决;
// 添加键盘监听
- (void)addNotification {
// 键盘即将出现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
// 键盘出现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
// 键盘即将消失
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
// 键盘消失
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self.webView evaluateJavaScript:@"document.body.scrollTop" completionHandler:nil];
}
- (void)keyboardDidShow:(NSNotification *)notification {
[self.webView evaluateJavaScript:@"document.body.scrollTop" completionHandler:nil];
}
- (void)keyboardWillHide:(NSNotification *)notification {
[self.webView evaluateJavaScript:@"document.body.scrollTop = 0;" completionHandler:nil];
}
- (void)keyboardDidHide:(NSNotification *)notification {
[self.webView evaluateJavaScript:@"document.body.scrollTop" completionHandler:nil];
}
2、数据交互是一个复杂的过程,所以需要一套规则来约束原生和Web APP;
(Web APP采用Vue框架)
// 原生调用JS方法
// JS写法
1.方法统一添加在main.js的methods中
2.把获取的参数赋值给data中的变量
3.页面获取通过this.$root.variable获取,variable为具体变量名
// 原生写法
[self.webView evaluateJavaScript:@“_vue.fn(参数1[,参数2…])” completionHandler:nil];
1._vue 固定写法
2.fn JS定义的具体方法名,参数可以多个
// JS调用原生方法
// JS写法
window.webkit.messageHandlers.mutual.postMessage(JSON);
1.mutual 为iOS定义的方法名,一般用一个就可以,通过参数type去区分功能模块
2.JSON 参数{type:xxx,data:xxx}为JSON格式对象
3.type 类型,不同的值对应不同的功能模块
4.data 传递的具体参数
// 原生写法
1.webview初始化的时候配置,方法名可以多个,一般用一个就可以
WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
[configuration.userContentController addScriptMessageHandler:self name:@"mutual"];
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
2.实现WKScriptMessageHandler协议
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"mutual"]) {
// message.name定义好的方法名
// message.body包含参数
// 进行原生的操作,比如上传图片之类
}
}
3、清理web app缓存数据
// 仅清理 localstorage 缓存的数据
[self.webView evaluateJavaScript:@"localStorage.clear()" completionHandler:^(id _Nullable obj, NSError * _Nullable error) {}];
// 清理 web app 对应类型的缓存,适用于iOS9及以后
NSArray *types = @[// 磁盘缓存
WKWebsiteDataTypeDiskCache,
// 内存中的缓存
WKWebsiteDataTypeMemoryCache,
// HTML离线Web应用程序缓存
WKWebsiteDataTypeOfflineWebApplicationCache,
// HTML本地存储
WKWebsiteDataTypeLocalStorage,
// Cookies 缓存
WKWebsiteDataTypeCookies,
// HTML会话存储
WKWebsiteDataTypeSessionStorage,
// IndexedDB数据库
WKWebsiteDataTypeIndexedDBDatabases,
// WebSQL数据库
WKWebsiteDataTypeWebSQLDatabases
];
NSSet *websiteDataTypes = [NSSet setWithArray:types];
NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
NSLog(@"清理成功");
}];
// 清理 web app 所有类型的缓存,适用于iOS9及以后
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate dateWithTimeIntervalSince1970:0] completionHandler:^{
NSLog(@"清理成功");
}];
4、
4.1、由于 iOS IDE 对 console.log() 支持不是很友好;
现目前有一个折中的调试办法,js中调用alert(param),iOS会弹出模态窗;
其中param为字符串类型参数,如果param是json对象,需要转化成字符串alert(JSON.stringify(param));
4.2、iOS中注入如下代码:
// alert
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"提示" message:message ? message : @"" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}])];
[self presentViewController:vc animated:YES completion:nil];
}
// confirm
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"提示" message:message ? message : @"" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler(NO);
}])];
[vc addAction:([UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler(YES);
}])];
[self presentViewController:vc animated:YES completion:nil];
}
// prompt
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
[vc addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.text = defaultText;
}];
[vc addAction:([UIAlertAction actionWithTitle:@"完成" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler(vc.textFields[0].text ? vc.textFields[0].text : @"");
}])];
[self presentViewController:vc animated:YES completion:nil];
}