Instantly share code, notes, and snippets.
WKWebview 设置cookie 的代码示例
// | |
// CICAppHostViewController.m | |
// myApp | |
// | |
// 需要h5和native 相互调用接口 页面使用此viewcontroller。 | |
// | |
// Created by hite on 9/22/15. | |
// Copyright © 2015 netease. All rights reserved. | |
// | |
#import "CICAppHostViewController.h" | |
#import "CICUserDefaults.h" | |
#import "Reachability.h" | |
#import "CICTemplateCacheManager.h" | |
#import "CICUDID.h" | |
#import "CICURLChecker.h" | |
#import "CICViewController+ErrorView.h" | |
#import "CICUserService.h" | |
#import "CICWebViewScrollPositionManager.h" | |
#import "CICCommonUI.h" | |
#import "CICNavigationBarResponse.h" | |
#import "CICAppLoggerResponse.h" | |
#import "CICAppHostCookie.h" | |
#import "CICScriptMessageDelegate.h" | |
@interface CICAppHostViewController () <UIScrollViewDelegate, WKNavigationDelegate, WKUIDelegate, CICErrorViewTapRefreshDelegate, WKScriptMessageHandler> | |
@property (nonatomic, strong) NSTimer *timer; | |
// 以下是页面加载的进度条 | |
@property (nonatomic, strong) NSTimer *progressorTimer; | |
@property (nonatomic, strong) NSTimer *clearProgressorTimer; | |
@property (nonatomic, strong) UIProgressView *progressorView; | |
@property (nonatomic, assign) BOOL isProgressorDone; | |
/** | |
wkwebview 加载本地文件 | |
*/ | |
@property (nonatomic, strong) NSString *localJavaScriptFile; | |
// 以下是注册 response 使用的属性 | |
/** | |
可处理 h5 action 的 response类的 NSString 形式。 | |
*/ | |
@property (nonatomic, strong) NSArray<NSString *> *responseClassNames; | |
/** | |
response类的 实例的缓存。 | |
*/ | |
@property (nonatomic, strong) NSMutableDictionary *responseClassObjs; | |
/** | |
提前初始化,需要在 加载的时候使用 | |
*/ | |
@property (nonatomic, strong) CICNavigationBarResponse *navBarResponse; | |
@end | |
static NSString *const kCICRequestProtocal = @"jsbridge://formyApp?param="; | |
static NSString *const kCICRequestItmsApp = @"itms-apps://"; | |
static NSString *const kCICRequestmyAppProtocal = @"myApp://"; | |
static NSString *const kCICScriptHandlerName = @"kCICScriptHandlerName"; | |
// 是否将客户端的 cookie 同步到 WKWebview 的 cookie 当中 | |
// 作为写 cookie 的假地址 | |
static NSString * _Nonnull kFakeCookieWebPageURLString = @"http://your.domain.com/xhr/user/getUid.do?26u-KQa-fKQ-3BD"; | |
@implementation CICAppHostViewController | |
- (void)viewDidAppear:(BOOL)animated | |
{ | |
[super viewDidAppear:animated]; | |
NSString *urlStr = nil; | |
if (self.webview && !self.webview.isLoading) { | |
urlStr = [[self.webview URL] absoluteString]; | |
} | |
if (urlStr.length == 0) { | |
urlStr = self.loadUrl; | |
} | |
[self sendMessageToWebPage:@"pageshow" param:@{ @"url" : urlStr?:@"null" }]; | |
} | |
- (void)viewDidDisappear:(BOOL)animated | |
{ | |
[super viewDidDisappear:animated]; | |
NSString *urlStr = [[self.webview URL] absoluteString]; | |
if (urlStr.length == 0) { | |
urlStr = self.loadUrl; | |
} | |
[self sendMessageToWebPage:@"pagehide" param:@{ @"url" : urlStr?:@"null" }]; | |
// | |
[self.timer invalidate]; | |
self.timer = nil; | |
[self.progressorTimer invalidate]; | |
self.progressorTimer = nil; | |
[self.clearProgressorTimer invalidate]; | |
self.clearProgressorTimer = nil; | |
} | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
if (self.isFullScreenWebview) { | |
self.automaticallyAdjustsScrollViewInsets = NO; | |
self.extendedLayoutIncludesOpaqueBars = YES; | |
} | |
[self initViews]; | |
} | |
- (void)initViews | |
{ | |
self.view.backgroundColor = [UIColor whiteColor]; | |
if (self.webview == nil) { | |
self.webview = [self getWebView]; | |
[self.view addSubview:self.webview]; | |
} | |
// | |
DDLogInfo(@"[JSBridge] load urltext: %@", self.loadUrl); | |
NSURL *actualUrl = [CICURL URLWithString:self.loadUrl]; | |
if (actualUrl == nil) { | |
[self showTextTip:@"请求地址为空,加载失败。" hideAfterDelay:5]; | |
DDLogError(@"[JSBridge] loadUlr 异常 = %@", self.loadUrl); | |
return; | |
} | |
// 添加url加载进度条。 | |
[self addWebviewProgressor]; | |
if ([CICAppHostCookie loginCookieHasBeenSynced] == NO) { | |
// | |
NSURL *cookieURL = [NSURL URLWithString:kFakeCookieWebPageURLString]; | |
NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:cookieURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:120]; | |
WKWebView *cookieWebview = [self getCookieWebview]; | |
[self.view addSubview:cookieWebview]; | |
[cookieWebview loadRequest:mutableRequest]; | |
DDLogInfo(@"[JSBridge] preload cookie for url = %@", self.loadUrl); | |
} else { | |
[self loadWebPage]; | |
} | |
} | |
- (void)addWebviewProgressor | |
{ | |
// 仿微信进度条 | |
self.progressorView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 20.0f)]; | |
// self.progressorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; | |
self.progressorView.trackTintColor = NYQColorFromRGB(0xffffff); | |
[self.view addSubview:self.progressorView]; | |
} | |
- (void)didReceiveMemoryWarning | |
{ | |
[super didReceiveMemoryWarning]; | |
// Dispose of any resources that can be recreated. | |
[[CICWebViewScrollPositionManager sharedInstance] clearAllCache]; | |
} | |
- (void)dealloc | |
{ | |
[self.webview.configuration.userContentController removeScriptMessageHandlerForName:kCICScriptHandlerName]; | |
self.webview.navigationDelegate = nil; | |
self.webview.scrollView.delegate = nil; | |
[self.webview stopLoading]; | |
[self.webview removeFromSuperview]; | |
self.webview = nil; | |
// 清理 response | |
[self.responseClassObjs enumerateKeysAndObjectsUsingBlock:^(NSString *key, id _Nonnull obj, BOOL * _Nonnull stop) { | |
obj = nil; | |
}]; | |
[self.responseClassObjs removeAllObjects]; | |
self.responseClassObjs = nil; | |
} | |
#pragma mark - public | |
- (void)setLocalFilePath:(NSString *)fileName javaScriptFileName:(NSString *)jsFileName | |
{ | |
self.loadUrl = fileName; | |
NSString *jsPath = [self.loadUrl stringByDeletingLastPathComponent]; | |
self.localJavaScriptFile = [jsPath stringByAppendingPathComponent:jsFileName]; | |
} | |
#pragma mark - UI相关 | |
- (void)loadWebPage | |
{ | |
NSURL *url = [CICURL URLWithString:self.loadUrl]; | |
if (url == nil) { | |
DDLogError(@"loadUrl is nil,loadUrl = %@", self.loadUrl); | |
[self showTextTip:@"加载网页地址错误"]; | |
return; | |
} | |
//检查网络是否联网; | |
DDLogDebug(@"[JSBridge] reachability check started"); | |
long startTime = [[[NSDate alloc] init] timeIntervalSince1970] * 1000; | |
Reachability *reachability = [Reachability reachabilityForInternetConnection]; | |
if ([reachability isReachable]) { | |
long endTime = [[[NSDate alloc] init] timeIntervalSince1970] * 1000; | |
DDLogDebug(@"[JSBridge] reachability check cosumed: %ld", endTime - startTime); | |
// | |
if ([CICURL isHttpOrHttpsUrl:url]) { | |
NSMutableURLRequest *mutableRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:120]; | |
[self.webview loadRequest:mutableRequest]; | |
} else { // 本地资源 | |
[self renderWebViewWithLocalFile:url]; | |
} | |
// 需要全屏但未设置,设置下 | |
if (self.isFullScreenWebview && self.isTransparentTopBar) { | |
[self.navigationController setNavigationBarHidden:YES animated:NO]; | |
} | |
[self toggleErrorView:NO title:nil subTitle:nil]; | |
} else { | |
[self toggleErrorView:YES title:nil subTitle:nil]; | |
} | |
} | |
/** | |
强制显示 加载失败页面 | |
@param show 是否显示 | |
@param title 第一行大字文案,可以为nil,默认显示加载失败 | |
@param subTitle 第二行文字,可以为nil,默认显示 点击屏幕,重新加载 | |
*/ | |
- (void)toggleErrorView:(BOOL)show title:(NSString *)title subTitle:(NSString *)subTitle | |
{ | |
if (show) { | |
if (self.errorView == nil) { | |
self.errorView = [self getErrorView:CICErrorViewOffline]; | |
[self.view addSubview:self.errorView]; | |
self.errorViewTapRefreshDelegate = self; | |
} | |
self.errorView.hidden = NO; | |
self.webview.hidden = YES; | |
if (!title) { | |
title = @"加载失败"; | |
} | |
if (!subTitle) { | |
subTitle = @"点击屏幕, 重新加载"; | |
} | |
[self configureErrorGuidTitle:title subTitle:subTitle]; | |
} else { | |
self.errorView.hidden = YES; | |
self.webview.hidden = NO; | |
} | |
} | |
- (void)renderWebViewWithLocalFile:(NSURL *)url | |
{ | |
NSError *err = nil; | |
NSString *appHtml = [NSString stringWithContentsOfFile:[url absoluteString] encoding:NSUTF8StringEncoding error:&err]; | |
if (err) { | |
DDLogError(@"[JSBridge] renderWebViewWithLocalFile failed.err = %@, url = %@", err, url); | |
} else { | |
NSString *baseUrlString = [url absoluteString]; | |
baseUrlString = [baseUrlString stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"/%@", baseUrlString.lastPathComponent] withString:@""]; | |
NSURL *baseUrl = [NSURL fileURLWithPath:baseUrlString isDirectory:YES]; | |
[self.webview loadHTMLString:appHtml baseURL:baseUrl]; | |
} | |
} | |
#pragma makr - errorView Tap | |
- (void)didTapErrorViewRefresh | |
{ | |
[self showLoading:@""]; | |
// | |
self.errorView.hidden = YES; | |
[self loadWebPage]; | |
// | |
[self hideHUD]; | |
} | |
#pragma mark - core | |
- (void)dispatchParsingParameterContent:(NSDictionary *)contentJSON | |
{ // 解析是否包含了日志 | |
NSMutableDictionary *paramDict = [[contentJSON objectForKey:@"param"] mutableCopy]; | |
id native_logs = [paramDict objectForKey:@"native_logs"]; | |
if (native_logs && [native_logs isKindOfClass: NSDictionary.class]){// 如果包含了logs的数组 | |
// 去掉日志数据,防止干扰 | |
[paramDict removeObjectForKey:@"native_logs"]; | |
// 检查是否需要发送log | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | |
NSString *key = @"CICAppLoggerResponse"; | |
CICAppLoggerResponse *loggerResp = [self.responseClassObjs objectForKey:key]; | |
if (loggerResp == nil) { | |
Class responseClass = NSClassFromString(key); | |
loggerResp = [[responseClass alloc] initWithAppHost:self]; | |
// 缓存住 | |
[self.responseClassObjs setObject:loggerResp forKey:key]; | |
[loggerResp sendLogOfDiscoveryToBI:native_logs]; | |
} | |
}); | |
} | |
// 增加对异常参数的catch | |
@try { | |
[self dispatchRequest:[contentJSON objectForKey:@"action"] parameter:paramDict]; | |
} @catch (NSException *exception) { | |
[self showTextTip:@"H5接口异常"]; | |
DDLogError(@"[JSBridge] h5接口解析异常,接口数据:%@", contentJSON); | |
} @finally { | |
} | |
} | |
// 延迟初始化; 短路判断 | |
- (void)dispatchRequest:(NSString *)action parameter:(NSDictionary *)paramDict | |
{ | |
BOOL catched = NO; | |
// 先过内置的 action handler | |
if ([@"showErrorView" isEqualToString:action]) { | |
[self toggleErrorView:YES title:[paramDict objectForKey:@"title"] subTitle:[paramDict objectForKey:@"subTitle"]]; | |
catched = YES; | |
} else { | |
// 进入第三方的response | |
for (NSInteger i = 0; i < self.responseClassNames.count; i++) { | |
NSString *key = [self.responseClassNames objectAtIndex:i]; | |
Class responseClass = NSClassFromString(key); | |
if ([responseClass isSupportedAction:action]) { | |
// 先判断是否可以响应,再决定初始化。 | |
id<CICAppHostProtocol> vc = [self.responseClassObjs objectForKey:key]; | |
if (vc == nil) { | |
vc = [[responseClass alloc] initWithAppHost:self]; | |
// 缓存住 | |
[self.responseClassObjs setObject:vc forKey:key]; | |
} | |
[vc handleAction:action withParam:paramDict]; | |
catched = YES; | |
break; | |
} | |
} | |
} | |
// | |
if (catched == NO) { | |
DDLogError(@"[JSBridge] action (%@) not supported yet.", action); | |
} | |
} | |
#pragma mark - wkwebview uidelegate | |
- (WKWebView *)webView:(WKWebView *)webView | |
createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration | |
forNavigationAction:(WKNavigationAction *)navigationAction | |
windowFeatures:(WKWindowFeatures *)windowFeatures | |
{ | |
if (!navigationAction.targetFrame.isMainFrame) { | |
[webView loadRequest:navigationAction.request]; | |
} | |
NSLog(@"%@", NSStringFromSelector(_cmd)); | |
return nil; | |
} | |
#pragma mark - wkwebview navigation delegate | |
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler | |
{ | |
DDLogDebug(@"%@", NSStringFromSelector(_cmd)); | |
NSURLRequest *request = navigationAction.request; | |
//此url解析规则自己定义 | |
NSString *rurl = [[request URL] absoluteString]; | |
[self logRequestAndResponse:rurl type:@"request"]; | |
WKNavigationActionPolicy policy = WKNavigationActionPolicyAllow; | |
if ([self isValidmyAppRequest:rurl]) { //使用myApp协议打开 | |
[CICNavHelper openURL:[CICURL URLWithString:rurl]]; | |
policy = WKNavigationActionPolicyCancel; | |
} else if ([self isValidRequest:rurl]) { | |
NSURL *actualUrl = [CICURL URLWithString:self.loadUrl]; | |
if (![[CICURLChecker sharedManager] checkURL:actualUrl forAuthorizationType:CICAuthorizationTypeAppHost]) { | |
DDLogError(@"invalid url visited : %@", self.loadUrl); | |
} else { | |
NSString *param = [rurl stringByReplacingOccurrencesOfString:kCICRequestProtocal withString:@""]; | |
NSDictionary *contentJSON = nil; | |
NSError *contentParseError; | |
if (param) { | |
param = [NSString stringDecodeURIComponent:param]; | |
contentJSON = [NSJSONSerialization JSONObjectWithData:[param dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&contentParseError]; | |
} | |
[self dispatchParsingParameterContent:contentJSON]; | |
} | |
// DDLogInfo(@"web view called > %@", param); | |
policy = WKNavigationActionPolicyCancel; | |
} else if ([self isItmsAppsRequest:rurl]) { //遇到 itms-apps://itunes.apple.com/cn/app/id992055304 主动 pop出去 | |
// URL Scheme and App Store links won't work https://github.com/ShingoFukuyama/WKWebViewTips#url-scheme-and-app-store-links-wont-work | |
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(popOutImmediately) userInfo:nil repeats:NO]; | |
[[UIApplication sharedApplication] openURL:[request URL]]; | |
policy = WKNavigationActionPolicyCancel; | |
} | |
// | |
decisionHandler(policy); | |
} | |
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation | |
{ | |
DDLogDebug(@"[JSBridge] didReceiveServerRedirectForProvisionalNavigation = %@", navigation); | |
} | |
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(nonnull WKNavigationResponse *)navigationResponse decisionHandler:(nonnull void (^)(WKNavigationResponsePolicy))decisionHandler | |
{ | |
NSURLResponse *resp = navigationResponse.response; | |
NSURL *url = [resp URL]; | |
DDLogDebug(@"[JSBridge] navigationResponse.url = %@", url); | |
decisionHandler(WKNavigationResponsePolicyAllow); | |
} | |
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation | |
{ | |
DDLogDebug(@"[JSBridge] didCommitNavigation = %@", navigation); | |
} | |
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation | |
{ | |
if (self.disabledProgressor) { | |
self.progressorView.hidden = YES; | |
} else { | |
// 清理旧的timer | |
[self.progressorTimer invalidate]; | |
self.progressorView.progress = 0; | |
self.isProgressorDone = NO; | |
self.progressorView.hidden = NO; | |
// 0.01667 is roughly 1/60, so it will update at 60 FPS | |
self.progressorTimer = [NSTimer scheduledTimerWithTimeInterval:0.01667 target:self selector:@selector(fakeProgressor) userInfo:nil repeats:YES]; | |
} | |
DDLogDebug(@"%@", NSStringFromSelector(_cmd)); | |
} | |
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation | |
{ | |
if (webView.isLoading) { | |
return; | |
} | |
NSURL *targetURL = webView.URL; | |
if ([CICAppHostCookie loginCookieHasBeenSynced] == NO && targetURL.query.length > 0 && [kFakeCookieWebPageURLString containsString:targetURL.query]) { | |
[CICAppHostCookie setLoginCookieHasBeenSynced:YES]; | |
// 加载真正的页面;此时已经有 App 的 cookie 存在了。 | |
[webView removeFromSuperview]; | |
[self loadWebPage]; | |
return; | |
} | |
//如果是全新加载页面,而不是从历史里弹出的情况下,需要渲染导航 | |
if (![self.webview canGoForward]) { | |
[self.navBarResponse initNavigationBarButtons]; | |
} | |
// | |
[self.navBarResponse initNavigationBarTitle]; | |
[self insertData:@{ @"ios" : @YES } intoPageWithVarName:@"platform"]; | |
//设置发现的后台接口; | |
NSDictionary *inserted = [self supportListByNow]; | |
[inserted enumerateKeysAndObjectsUsingBlock:^(NSString *keyStr, id obj, BOOL *stop) { | |
[self insertData:obj intoPageWithVarName:keyStr]; | |
}]; | |
[self sendMessageToWebPage:@"onready" param:@{}]; | |
self.isProgressorDone = YES; | |
// 防止内存飙升 | |
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"]; | |
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"]; | |
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"]; | |
[[NSUserDefaults standardUserDefaults] synchronize]; | |
// | |
[self dealWithViewHistory]; | |
DDLogDebug(@"%@", NSStringFromSelector(_cmd)); | |
} | |
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message | |
{ | |
if ([message.name isEqualToString:kCICScriptHandlerName]) { | |
// | |
DDLogDebug(@"%@",message.body); | |
NSDictionary *contentJSON = message.body; | |
[self dispatchParsingParameterContent:contentJSON]; | |
} else { | |
#if CIC_TEST == 1 | |
[self showTextTip:@"没有实现的接口"]; | |
#endif | |
DDLogError(@"[JSBridge] unknown methods : %@", message.name); | |
} | |
} | |
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error | |
{ | |
self.isProgressorDone = YES; | |
DDLogDebug(@"%@", NSStringFromSelector(_cmd)); | |
} | |
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error | |
{ | |
self.isProgressorDone = YES; | |
DDLogDebug(@"%@", NSStringFromSelector(_cmd)); | |
[self showTextTip:@"加载页面内容时出错"]; | |
DDLogInfo(@"[JSBridge] load page error = %@", error); | |
} | |
- (void)popOutImmediately | |
{ | |
if (self.fromPresented) { | |
[self dismissViewControllerAnimated:NO completion:nil]; | |
} else { | |
[self.navigationController popViewControllerAnimated:NO]; | |
} | |
} | |
- (void)fakeProgressor | |
{ | |
// DDLogDebug(@"[JSBridge] progress = %f", self.webview.estimatedProgress); | |
if (self.isProgressorDone) { | |
[self.progressorView setProgress:1 animated:YES]; | |
[self.progressorTimer invalidate]; | |
// 完成之后clear进度 | |
self.clearProgressorTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(clearProgressor) userInfo:nil repeats:NO]; | |
} else { | |
self.progressorView.progress = self.webview.estimatedProgress; | |
} | |
} | |
- (void)clearProgressor | |
{ | |
self.progressorView.hidden = YES; | |
[self.clearProgressorTimer invalidate]; | |
} | |
#pragma mark - supportType | |
- (void)executeJavaScriptString:(NSString *)javaScriptString | |
{ | |
[self.webview evaluateJavaScript:javaScriptString completionHandler:nil]; | |
} | |
#pragma mark - innner | |
- (BOOL)isValidRequest:(NSString *)url | |
{ | |
return [url hasPrefix:kCICRequestProtocal]; | |
} | |
- (BOOL)isItmsAppsRequest:(NSString *)url | |
{ | |
// itms-appss://itunes.apple.com/cn/app/id992055304 | |
// https://itunes.apple.com/cn/app/id992055304 | |
NSArray<NSString *> *prefixs = @[ kCICRequestItmsApp, @"itms-appss://", @"itms-services://", @"itmss://" ]; | |
BOOL __block pass = NO; | |
[prefixs enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { | |
if ([url hasPrefix:obj]) { | |
pass = YES; | |
*stop = YES; | |
} | |
}]; | |
return pass; | |
} | |
- (BOOL)isValidmyAppRequest:(NSString *)url | |
{ | |
return [url hasPrefix:kCICRequestmyAppProtocal]; | |
} | |
- (void)callbackFunctionOnWebPage:(NSString *)actionName param:(NSDictionary *)paramDict | |
{ | |
[self __sendMessageToWebPage:actionName funcName:@"__callback" param:paramDict]; | |
} | |
- (void)sendMessageToWebPage:(NSString *)actionName param:(NSDictionary *)paramDict | |
{ | |
[self __sendMessageToWebPage:actionName funcName:@"__fire" param:paramDict]; | |
} | |
- (void)__sendMessageToWebPage:(NSString *)actionName funcName:(NSString *)funcName param:(NSDictionary *)paramDict | |
{ | |
NSData *objectOfJSON = nil; | |
NSError *contentParseError; | |
objectOfJSON = [NSJSONSerialization dataWithJSONObject:paramDict options:NSJSONWritingPrettyPrinted error:&contentParseError]; | |
NSString *jsCode = [NSString stringWithFormat:@"window.appHost.%@('%@',%@);", funcName, actionName, [[NSString alloc] initWithData:objectOfJSON encoding:NSUTF8StringEncoding]]; | |
[self logRequestAndResponse:jsCode type:@"response"]; | |
jsCode = [jsCode stringByReplacingOccurrencesOfString:@"\n" withString:@""]; | |
[self executeJavaScriptString:jsCode]; | |
// DDLogInfo(@"invoke js: %@", jsCode); | |
} | |
- (void)logRequestAndResponse:(NSString *)str type:(NSString *)type | |
{ | |
NSUInteger toIndex = MIN(500, str.length); | |
DDLogDebug(@"[JSBridge] debug type: %@ , url : %@", type, [str substringToIndex:toIndex]); | |
} | |
#pragma mark - getter | |
- (CICNavigationBarResponse *)navBarResponse | |
{ | |
if (_navBarResponse == nil) { | |
// 先检测是否存在于缓存里 | |
_navBarResponse = [self.responseClassObjs objectForKey:@"CICNavigationBarResponse"]; | |
// 预初始化 | |
if (_navBarResponse == nil) { | |
_navBarResponse = [[CICNavigationBarResponse alloc] initWithAppHost:self]; | |
[self.responseClassObjs setObject:_navBarResponse forKey:@"CICNavigationBarResponse"]; | |
} | |
} | |
return _navBarResponse; | |
} | |
- (WKWebView *)getCookieWebview | |
{ | |
// 设置加载页面完毕后,里面的后续请求,如 xhr 请求使用的cookie | |
WKUserContentController *userContentController = [WKUserContentController new]; | |
WKWebViewConfiguration *webViewConfig = [[WKWebViewConfiguration alloc] init]; | |
webViewConfig.userContentController = userContentController; | |
webViewConfig.processPool = [CICAppHostCookie sharedPoolManager]; | |
NSMutableArray<NSString *> *oldCookies = [CICAppHostCookie cookieJavaScriptArray]; | |
[oldCookies enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { | |
NSString *setCookie = [NSString stringWithFormat:@"document.cookie='%@';", obj]; | |
WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:setCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; | |
[userContentController addUserScript:cookieScript]; | |
}]; | |
#if CIC_TEST == 1 | |
DDLogInfo(@"[JSBridge] getWebView. oldCookies = %@", oldCookies); | |
#endif | |
WKWebView *webview = [[WKWebView alloc] initWithFrame:CGRectMake(0, -1, SCREEN_WIDTH,ONE_PIXEL) configuration:webViewConfig]; | |
webview.navigationDelegate = self; | |
webview.UIDelegate = self; | |
return webview; | |
} | |
- (WKWebView *)getWebView | |
{ | |
// 设置加载页面完毕后,里面的后续请求,如 xhr 请求使用的cookie | |
WKUserContentController *userContentController = [WKUserContentController new]; | |
__weak typeof(self) weakSelf = self; | |
[userContentController addScriptMessageHandler:[[CICScriptMessageDelegate alloc] initWithDelegate:weakSelf] name:kCICScriptHandlerName]; | |
WKWebViewConfiguration *webViewConfig = [[WKWebViewConfiguration alloc] init]; | |
webViewConfig.userContentController = userContentController; | |
webViewConfig.allowsInlineMediaPlayback = YES; | |
webViewConfig.processPool = [CICAppHostCookie sharedPoolManager]; | |
if (self.localJavaScriptFile.length > 0) { | |
NSError *err = nil; | |
NSString *jScript = [NSString stringWithContentsOfFile:self.localJavaScriptFile encoding:NSUTF8StringEncoding error:&err]; | |
if (err == nil) { | |
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; | |
[userContentController addUserScript:wkUScript]; | |
} else { | |
DDLogDebug(@"[JSBridge] Load local javaScript file failed. erro = %@", err); | |
} | |
} | |
WKWebView *webview = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT - (self.isTransparentTopBar ? 0 : NAVIGATION_BAR_HEIGHT)) configuration:webViewConfig]; | |
webview.scrollView.contentSize = CGSizeMake(CGRectGetWidth(webview.frame), CGRectGetHeight(webview.frame)); | |
webview.navigationDelegate = self; | |
webview.UIDelegate = self; | |
webview.scrollView.delegate = self; | |
return webview; | |
} | |
#pragma mark - vc settings | |
/** | |
* 导航栏是否显示。这里透明导航栏是使用自定义的导航实现。 | |
* 所以接口需要透明导航的时候,其实是不显示导航,显示自定义导航。 | |
* | |
* @return | |
*/ | |
- (BOOL)shouldShowNavigationBar | |
{ | |
Reachability *reachability = [Reachability reachabilityForInternetConnection]; | |
if (![reachability isReachable]) { | |
return YES; | |
} | |
return !self.isTransparentTopBar; | |
} | |
- (BOOL)shouldHidesBottomBarWhenPushed | |
{ | |
return !self.showBottomBar; | |
} | |
- (UIStatusBarStyle)preferredStatusBarStyle | |
{ | |
return self.navBarStyle; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment