博客> WKWebView的方法的使用与配置
WKWebView的方法的使用与配置
2017-11-21 04:25 评论:0 阅读:567 yangdongming
WKWebView cookies WK代理方法的使用
#import "WKDelegateController.h"
#import "WXHWebKitSupport.h"
第一个类绕过代理防止释放不了当前控制器,第二个类单例唯一缓存池,避免每次cookies丢失

.h
#import <UIKit>
#import <WebKit>
@protocol WKDelegate <NSObject>
- (void)userContentController:(WKUserContentController *)userContentController     didReceiveScriptMessage:(WKScriptMessage *)message;
@end
@interface WKDelegateController : UIViewController<WKScriptMessageHandler>
@property (weak , nonatomic) id<WKDelegate> delegate;
@end
.m
#import "WKDelegateController.h"
@interface WKDelegateController ()
@end
@implementation WKDelegateController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)userContentController:(WKUserContentController *)userContentController     didReceiveScriptMessage:(WKScriptMessage *)message{
    if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
        [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
    }
}

.h
#import <Foundation>
#import <WebKit>
@interface WXHWebKitSupport : NSObject
@property (nonatomic, strong,readonly) WKProcessPool *processPool;
+ (instancetype)sharedSupport;
+ (WKWebView *)createSharableWKWebView:(WKUserContentController *)userController withFrame:    (CGRect)frame;
- (void)removeCookiesForPool;
@end
.m
#import "WXHWebKitSupport.h"
@interface WXHWebKitSupport ()
@property (nonatomic, strong) WKProcessPool *processPool;
@end
@implementation WXHWebKitSupport
+ (instancetype)sharedSupport {
    static WXHWebKitSupport *_instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [WXHWebKitSupport new];
    });
    return  _instance;
}
- (instancetype)init {
    if (self = [super init]) {
        self.processPool = [WKProcessPool new];
    }
    return self;
}
- (WKProcessPool *)processPool{
    if (_processPool == nil) { 
        _processPool = [WKProcessPool new];
    } 
    return _processPool;
}

+ (WKWebView *)createSharableWKWebView:(WKUserContentController *)userController withFrame:    (CGRect)frame{    
NSMutableString *cookies = [NSMutableString string];
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[cookies copy]
                                                     injectionTime:WKUserScriptInjectionTimeAtDocumentStart
                                                  forMainFrameOnly:NO];
[userController addUserScript:cookieScript];

WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
configuration.preferences = [WKPreferences new];//偏好设置
configuration.preferences.minimumFontSize = 10;//最小字体
configuration.preferences.javaScriptEnabled = YES;//是否支持javaScript
configuration.preferences.javaScriptCanOpenWindowsAutomatically = NO;//是否能自动打开窗口
// 一下两个属性是允许H5视屏自动播放,并且全屏,可忽略
configuration.allowsInlineMediaPlayback = YES;
configuration.mediaPlaybackRequiresUserAction = NO;
// 全局使用同一个processPool
configuration.processPool = [[WXHWebKitSupport sharedSupport] processPool];
configuration.userContentController = userController;
WKWebView *wk_webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];   
return wk_webView;

}

  • (void)removeCookiesForPool{
    self.processPool = nil; } @end

    // 1,预加载,在loadView时创建WKWebView并配置它,在didLoad中add到self.view上(如果当前页面只有 webVeiw直接在loadView中设置wkwebView为当前控制器的根视图:self.view=self.webView)注意cookies 的配置和清除都得倒loadRequest之前配置。

  • (void)loadView {

    [super loadView];
    WKUserContentController *userContentController = [WKUserContentController new];
    Managers *managers=[AppDelegate getManagers];
    NSURL *url = [NSURL URLWithString:BseUrl];
    NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
    //
    WKDelegateController * delegateController = [[WKDelegateController alloc]init];
    delegateController.delegate = self;
    //利用代理绕过引用自身
    [userContentController addScriptMessageHandler:delegateController name:@"toLoginApp"];
    [userContentController addScriptMessageHandler:delegateController name:@"toAppShare"];
    [userContentController addScriptMessageHandler:delegateController name:@"toLogoutApp"];
    //JS注入方法
    NSString *JS_Naitve =@" var WxhNative ={ \
    toLoginApp : function(obj) { \
    window.webkit.messageHandlers.toLoginApp.postMessage({body:obj});\
    },\
    \
    toAppShare : function(obj) { \
    window.webkit.messageHandlers.toAppShare.postMessage({body:obj});\
    },\
    \
    toLogoutApp : function() { \
    window.webkit.messageHandlers.toLogoutApp.postMessage();\
    }\
    }";
    WKUserScript *script = [[WKUserScript alloc] initWithSource:JS_Naitve     injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    [userContentController addUserScript:script];
    NSArray     *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *plistPath1 = [paths objectAtIndex:0];
    //得到完整的文件名
    NSString *filename=[plistPath1 stringByAppendingPathComponent:@"Cookies.plist"];
    NSError *error;
    NSString *cookiesString = [NSString stringWithContentsOfFile:filename     e    ncoding:NSUTF8StringEncoding error:&error];
    [request setValue:[self readCurrentCookieWithDomain:cookiesString] forHTTPHeaderField:@"Cookie"];
    //清空必须放在创建WKweibView之前
    if (isClearCoookies) {//全局控制某个时候退出登录状态,清空cookies
        [self clearCookies];
    }
      _webView = [WXHWebKitSupport createSharableWKWebView:userContentController     withFrame:CGRectMake(0, statusBarHeight, kScreenWidth,kScreenHeight-statusBarHeight)];
       //增加进度监听
     [_webView addObserver:self forKeyPath:@"estimatedProgress"     options:NSKeyValueObservingOptionNew context:nil];
        _webView.scrollView.bounces = NO;
        _webView.UIDelegate = self;
        _webView.navigationDelegate= self;
        [_webView loadRequest:request];
        UIView *progress = [[UIView alloc]initWithFrame:CGRectMake(0, -progressHeight, CGRectGetWidth(self.webView.frame), progressHeight)];
        progress.backgroundColor = [UIColor clearColor];
        [self.webView addSubview:progress];
        CALayer *layer = [CALayer layer];
        layer.frame = CGRectMake(0, 0, 0, progressHeight);
        layer.backgroundColor = [UIColor colorWithRed:38/255.0 green:160/255.0 blue:35/255.0 alpha:1].CGColor;
        [progress.layer addSublayer:layer];
        self.progresslayer = layer;
     }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.  
        [self.view addSubview:_webView];
    }
    
    //拼接cookies
    - (NSString *)readCurrentCookieWithDomain:(NSString *)domainStr{
        if (domainStr.length>1) {
        NSMutableString *cookies = [NSMutableString stringWithFormat:@"%@",domainStr];
        [cookies deleteCharactersInRange:NSMakeRange(domainStr.length - 1, 1)];
        return cookies;
        }
        else{
            NSHTTPCookieStorage*cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
            NSMutableString * cookieString = [[NSMutableString alloc]init];
            for (NSHTTPCookie*cookie in [cookieJar cookies]) {
            [cookieString appendFormat:@"%@=%@;",cookie.name,cookie.value];
      }
    //删除最后一个“;”
    if(cookieString.length>1){
    [cookieString deleteCharactersInRange:NSMakeRange(cookieString.length - 1, 1)];
    }
    return cookieString;

    }

    // #pragma mark-WKWebViewDelegate /在WkWebView接收到Response后,将Response带的Cookies取出,然后直接放入 [NSHTTPCookieStorage sharedHTTPCookieStorage]/

    • (void)webView:(WKWebView )webView decidePolicyForNavigationResponse:(WKNavigationResponse )navigationResponse decisionHandler:(void (^) (WKNavigationResponsePolicy))decisionHandler{ NSHTTPURLResponse response = (NSHTTPURLResponse )navigationResponse.response; NSArray cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL]; for (NSHTTPCookie cookie in cookies) { [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; NSLog(@"wkwebview中的cookie:%@", cookie); } //读取wkwebview中的cookie 方法2 读取Set-Cookie字段 // NSString cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"]; // NSLog(@"wkwebview中的cookie:%@", cookieString); //看看存入到了NSHTTPCookieStorage了没有 NSHTTPCookieStorage cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage]; NSMutableString needSavecookieString = [[NSMutableString alloc] init]; for (NSHTTPCookie cookie in cookieJar2.cookies) { NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie); [needSavecookieString stringByAppendingString:[NSString stringWithFormat:@"%@=%@;", cookie.name, cookie.value]]; } _cookiesStr = needSavecookieString; decisionHandler(WKNavigationResponsePolicyAllow); }

    /新开子页面/ -(WKWebView )webView:(WKWebView )webView createWebViewWithConfiguration: (WKWebViewConfiguration )configuration forNavigationAction:(WKNavigationAction )navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures { if (!navigationAction.targetFrame.isMainFrame) { [webView loadRequest:navigationAction.request]; } return nil; } //

  • (void)webView:(WKWebView )webView decidePolicyForNavigationAction:(WKNavigationAction )navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURL URL = navigationAction.request.URL; NSString scheme = [URL scheme]; UIApplication *app = [UIApplication sharedApplication]; // 打电话 if ([scheme isEqualToString:@"tel"]) { if ([app canOpenURL:URL]) { [app openURL:URL]; // 一定要加上这句,否则会打开新页面 decisionHandler(WKNavigationActionPolicyCancel); return; } } decisionHandler(WKNavigationActionPolicyAllow); }

////iOS9https权限认证

  • (void)webView:(WKWebView )webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge )challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential credential))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([challenge previousFailureCount] == 0) { NSURLCredential credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } } else { completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } }

/在完全加载完成后需要重新给WKWebView设置Cookie呢?如果你不这样做的话很有可能因为a标签跳转,导致下一次跳转的时候Cookie丢失。/

  • (void)webView:(WKWebView )webView didFinishNavigation:(WKNavigation )navigation { NSHTTPCookieStorage cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; //js函数 NSString JSFuncString = @"function setCookie(name,value,expires)\ {\ var oDate=new Date();\ oDate.setDate(oDate.getDate()+expires);\ [removed]=name+'='+value+';expires='+oDate+';path=/'\ }\ function getCookie(name)\ {\ var arr = [removed].match(new RegExp('(^| )'+name+'=({FNXX==XXFN})(;|$)'));\ 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) [removed]= 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 evaluate[removed]JSCookieString completionHandler:^(id obj, NSError * _Nullable error) { NSLog(@"%@",error); }]; }

//监听

  • (void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void )context{ if ([keyPath isEqualToString:@"estimatedProgress"]) { self.progresslayer.opacity = 1; //不要让进度条倒着走...有时候goback会出现这种情况 if ([change[@"new"] floatValue] < [change[@"old"] floatValue]) { return; } self.progresslayer.frame = CGRectMake(0, 0, self.view.bounds.size.width [change[@"new"] floatValue], progressHeight); if ([change[@"new"] floatValue] == 1) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.4 NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.progresslayer.opacity = 0; }); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5 NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.progresslayer.frame = CGRectMake(0, 0, 0, progressHeight); }); } }else{ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } }

    // #pragma mark - WKScriptMessageHandler

    • (void)webView:(WKWebView )webView runJavaScriptAlertPanelWithMessage:(NSString )message initiatedByFrame:(WKFrameInfo )frame completionHandler:(void (^)(void))completionHandler { // js 里面的alert实现,如果不实现,网页的alert函数无效 UIAlertController alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { completionHandler(); }]]; [self presentViewController:alertController animated:YES completion:^{}]; }

    • (void)webView:(WKWebView )webView runJavaScriptConfirmPanelWithMessage:(NSString )message initiatedByFrame:(WKFrameInfo )frame completionHandler:(void (^)(BOOL))completionHandler { // js 里面的alert实现,如果不实现,网页的alert函数无效 , UIAlertController alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction action) { completionHandler(YES); }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction action){ completionHandler(NO); }]]; [self presentViewController:alertController animated:YES completion:^{}]; }

    //检测到jS方法

    • (void)userContentController:(WKUserContentController )userContentController didReceiveScriptMessage:(WKScriptMessage )message{ NSString methodName = message.name; NSDictionary obj = message.body; NSLog(@"%@\n%@",methodName,obj); if ([methodName isEqualToString:@"toLoginApp"]) { if (obj) { //执行某操作
      } } if ([methodName isEqualToString:@"toAppShare"]) { if (obj) { //执行某操作 } } if ([methodName isEqualToString:@"toLogoutApp"]) { //执行某操作 } }

      //本地存cookies -(void)saveSessID{ if (_cookiesStr) { NSArray paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); NSString plistPath1 = [paths objectAtIndex:0]; //得到完整的文件名 NSString filename=[plistPath1 stringByAppendingPathComponent:@"banshouCookies.plist"]; NSError error; if([_cookiesStr writeToFile:filename atomically:YES encoding:NSUTF8StringEncoding error:&error]){ NSLog(@"存Cookies 成功"); } } }

    //清空缓存/cookies

    • (void)clearCookies{ //重置缓存池 [[WXHWebKitSupport sharedSupport] removeCookiesForPool]; //iOS8.0 NSString libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"]; NSError *errors; [[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors]; }

      //释放

    • (void)dealloc{ [_webView removeObserver:self forKeyPath:@"estimatedProgress"]; [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"toLoginAppPassValue"]; [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"toAppSharePassValue"]; [[_webView configuration].userContentController removeScriptMessageHandlerForName:@"toLogoutAppPassValue"]; [_webView loadHTMLString:@"" baseURL:nil]; [_webView stopLoading]; [_webView removeFromSuperview]; _webView = nil; [[NSURLCache sharedURLCache] removeAllCachedResponses]; [[NSURLCache sharedURLCache] setDiskCapacity:0]; [[NSURLCache sharedURLCache] setMemoryCapacity:0]; NSLog(@"释放了webview"); if (_progresslayer) { [_progresslayer removeFromSuperlayer]; _progresslayer = nil; } self.view = nil; }
收藏
0
sina weixin mail 回到顶部