WKWebView比UIWebView的好处,不多说
直接上代码
webview的控制器
@interface ILWebActTestViewController ()
@property (strong, nonatomic) G_Nav *nav;
@property (nonatomic ,strong) WKWebView * actWKWebView;
@property (nonatomic,strong)WKUserContentController * contentController;
@end
@implementation ILWebActTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initUI];
[self initWebView];
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.tabBarController.tabBar.hidden = YES;
}
-(void)initUI{
self.view.backgroundColor = [UIColor whiteColor];
self.nav = [G_Nav new];
self.nav.backStr = @"返回";
[self.nav setG_Nav:self.view];
self.nav.bgView.backgroundColor= COLOR_RGBA(38, 184, 242, 1.0);
self.nav.tittleLabel.textColor =[UIColor whiteColor];
self.nav.tittleLabel.text = @"搞事情";
self.nav.delegate = self;
}
#pragma mark - 初始化WebView
-(void)initWebView{
NSMutableURLRequest*urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_url]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
//要给request加上当前登录信息的cookies,要不然身份验证通不过
[urlRequest addValue:[self readCurrentCookie] forHTTPHeaderField:@"Cookie"];
//使用WKUserContentController实现js native交互,简单的说就是先注册约定好的方法,然后再调用
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init];
_contentController = [[WKUserContentController alloc] init];
configuration.userContentController = _contentController;
//kWeakself;
//注册方法
//下面这句代码造成无法释放内存。(ps:试了下用weak指针还是不能释放,不知道是什么原因。)因此还需要进一步改进,正确的写法是用一个新的controller来处理,新的controller再绕用delegate绕回来
//[contentController addScriptMessageHandler:weakSelf name:@"Share"];
ILWebWkDelegateController *delegateController = [[ILWebWkDelegateController alloc] init];
delegateController.delegate = self;
[_contentController addScriptMessageHandler:delegateController name:@"Share"];
_actWKWebView = [[WKWebView alloc ] initWithFrame:CGRectZero configuration:configuration];
[self.view addSubview:_actWKWebView];
[_actWKWebView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(kGNavHeight);
make.left.right.bottom.equalTo(self.view);
}];
[_actWKWebView loadRequest:urlRequest];
_actWKWebView.UIDelegate = self;
_actWKWebView.navigationDelegate = self;
}
#pragma mark - G_NavDelegate
-(void)clickBackBt:(UIButton*)sender{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - WKUIDelegate
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"加载数据的时候的 页面开始加载的时候失败");
}
- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation{
NSLog(@"当页面开始返回内容");
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
NSLog(@"当页面加载完成后调用");
}
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{
NSLog(@"在接收数据的过程中加载失败");
}
// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
}
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
NSLog(@"%@",navigationResponse.response.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationResponsePolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSLog(@"%@",navigationAction.request.URL.absoluteString);
//允许跳转
decisionHandler(WKNavigationActionPolicyAllow);
//不允许跳转
//decisionHandler(WKNavigationActionPolicyCancel);
}
#pragma mark - WKWeakDelegate
- (void)EYUserContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
if ([message.name isEqualToString:@"Share"]) {
[self ShareWithInformation:message.body];
}
}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
if ([message.name isEqualToString:@"Share"]) {
[self ShareWithInformation:message.body];
}
}
#pragma mark - 获取当前cookies
/**
以前UIWebView会自动去NSHTTPCookieStorage中读取cookie,但是WKWebView并不会去读取,因此导致cookie丢失以及一系列问题,解决方式就是在request中手动帮其添加上
但是这只能解决第一次进入的cookie问题,如果页面内跳转(a标签等)还是取不到cookie,因此还要再加代码
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
//取出cookie
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//js函数
NSString *JSFuncString =
@"function setCookie(name,value,expires)\
{\
var oDate=new Date();\
oDate.setDate(oDate.getDate()+expires);\
document.cookie=name+'='+value+';expires='+oDate+';path=/'\
}\
function getCookie(name)\
{\
var arr = document.cookie.match(new RegExp('(^| )'+name+'=([^;]*)(;|$)'));\
if(arr != null) return unescape(arr[2]); return null;\
}\
function delCookie(name)\
{\
var exp = new Date();\
exp.setTime(exp.getTime() - 1);\
var cval=getCookie(name);\
if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\
}";
//拼凑js字符串
NSMutableString *JSCookieString = JSFuncString.mutableCopy;
for (NSHTTPCookie *cookie in cookieStorage.cookies) {
NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
[JSCookieString appendString:excuteJSString];
}
//执行js
[webView evaluateJavaScript:JSCookieString completionHandler:nil];
}
@return cookies 字符串
*/
- (NSString*)readCurrentCookie{
NSArray *cookies =[ILUser cookies];
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:[cookies objectAtIndex:0] forKey:NSHTTPCookieName];
[cookieProperties setObject:[cookies objectAtIndex:1] forKey:NSHTTPCookieValue];
[cookieProperties setObject:[cookies objectAtIndex:3] forKey:NSHTTPCookieDomain];
[cookieProperties setObject:[cookies objectAtIndex:4] forKey:NSHTTPCookiePath];
if (cookieProperties == nil) {
return nil;
}else{
NSHTTPCookieStorage*cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSMutableString *cookieString = [[NSMutableString alloc] init];
for (NSHTTPCookie*cookie in [cookieJar cookies]) {
[cookieString appendFormat:@"%@=%@;",cookie.name,cookie.value];
}
//删除最后一个“;”
[cookieString deleteCharactersInRange:NSMakeRange(cookieString.length - 1, 1)];
return cookieString;
}
}
#pragma mark - 处理分享
- (void)ShareWithInformation:(NSDictionary *)dic {
if (![dic isKindOfClass:[NSDictionary class]]) {
return;
}
[self showThirdShareView:[dic objectForKey:@"url"]];
}
- (void)showThirdShareView:(NSString *)shareURL {
NSArray *iamgeArr = @[@"ic_pyq",@"ic_wxchat",@"ic_zone",@"ic_qq"];
NSArray *titleArr = @[@"朋友圈",@"微信",@"QQ空间",@"QQ"];
NSString *shareTitle = @"我有一个官方出品的陕旅版英语APP推荐给你,电子课本免费用!";
NSString *sahreDescription = @"官方出品,教材配套,权威内容,让我的英语学习so easy!";
UIImage *shareImage = [UIImage imageNamed:@"shareIcon"];
//分享页面
ThirdShareView *thirdShareView = [[ThirdShareView alloc] initWithTitle:titleArr AndWithImage:iamgeArr AndOffset:NO];
thirdShareView.selectBlock=^(NSString *platForm){
//分享对应platframe
ThirdShareModel *thirdModel = [[ThirdShareModel alloc] init];
if ([platForm isEqualToString:@"QQ"]) {
[thirdModel qqShare:qqSceneFriend sharetype:contentTypeWeb shareText:sahreDescription image:shareImage title:shareTitle URL:shareURL];
}else if ([platForm isEqualToString:@"QQ空间"]) {
[thirdModel qqShare:qqSceneZone sharetype:contentTypeWeb shareText:sahreDescription image:shareImage title:shareTitle URL:shareURL];
}else if ([platForm isEqualToString:@"微信"]) {
[thirdModel wxShare:wxSceneSession sharetype:contentTypeWeb shareText:sahreDescription image:shareImage title:shareTitle URL:shareURL];
}else if ([platForm isEqualToString:@"朋友圈"]) {
[thirdModel wxShare:wxSceneTimeline sharetype:contentTypeWeb shareText:sahreDescription image:shareImage title:shareTitle URL:shareURL];
}
};
UIApplication *applaction = [UIApplication sharedApplication];
[applaction.keyWindow addSubview:thirdShareView];
}
-(void)dealloc{
//这里需要注意,前面增加过的方法一定要remove掉。
[_contentController removeScriptMessageHandlerForName:@"Share"];
}
为了防止循环引用的代理控制代码
.m
@interface ILWebWkDelegateController ()
@end
@implementation ILWebWkDelegateController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([self.delegate respondsToSelector:@selector(EYUserContentController:didReceiveScriptMessage:)]) {
[self.delegate EYUserContentController:userContentController didReceiveScriptMessage:message];
}
}
@end
.h
@protocol WKWeakDelegate
- (void)EYUserContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
@end
@interface ILWebWkDelegateController : UIViewController
@property (weak , nonatomic) id delegate;
@end
参考