美文网首页
WKWebView 使用

WKWebView 使用

作者: 枯竹流过岁月 | 来源:发表于2020-11-10 11:38 被阅读0次

    import "JspWebViewController.h"

    import "LoginViewController.h"

    import "AppDelegate.h"

    import "IdleWindow.h"

    import "UIDevice+TFDevice.h"

    import <WebKit/WebKit.h>

    @interface JspWebViewController ()<WKScriptMessageHandler,WKUIDelegate,WKNavigationDelegate> //(遵守的协议)
    @property (nonatomic, strong) WKWebView *webView;
    @property (strong, nonatomic) UIBarButtonItem *backItem0;
    @property (strong, nonatomic) UIButton *btn;
    @property(nonatomic,strong)UIAlertView *loadingAlert;
    //@property (strong,nonatomic) UIAlertController *loadingAlert;

    @end

    @implementation JspWebViewController

    • (void)viewDidLoad {
      [super viewDidLoad];
      [self configWKWebView];

    }

    • (void)configWKWebView{

      WKUserContentController *userContentController = [[WKUserContentController alloc] init];

      //获取cookie
      NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
      NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
      NSMutableString *cookieValue = [NSMutableString string];
      NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
      for(NSHTTPCookie *cookie in [cookieStorage cookies]) {
      [cookieDic setObject:cookie.value forKey:cookie.name];
      }
      //cookie去重复,先放到字典中再去重
      for(NSString *key in cookieDic.allKeys){
      NSString *appendingStr = [NSString stringWithFormat:@"%@=%@",key,[cookieDic valueForKey:key]];
      [cookieValue appendString:appendingStr];
      }

      //js注入cookie,防止从请求页面返回后再次请求页面失败,ios 11以前系统
      NSString *cookieSource = [[@"document.cookie = '" stringByAppendingString:cookieValue] stringByAppendingString:@"'"];
      WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:cookieSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
      [userContentController addUserScript:cookieScript];

      //测试将参数保存到缓存localStorage里,方便后台调用。
      NSString *sendTocen = [NSString stringWithFormat:@"localStorage.setItem("accessToken",'%@');localStorage.setItem("testItem",'%@');",[self getUserName],[self getUserSP]];
      //设置js和oc交互。可以设置多个
      WKUserScript *script = [[WKUserScript alloc] initWithSource:sendTocen injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
      [userContentController addScriptMessageHandler:[WeakScriptMessageDelegate alloc] name:@"iOS"];
      [userContentController addUserScript:script];

      //WkwebView 配置协议
      WKWebViewConfiguration *config = [WKWebViewConfiguration new];
      config.userContentController = userContentController;

      config.preferences.javaScriptEnabled = YES;
      config.preferences.javaScriptCanOpenWindowsAutomatically = YES;
      config.suppressesIncrementalRendering = YES; // 是否支持记忆读取
      [config.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];
      if (@available(iOS 10.0, *)) {
      [config setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"];
      }
      //定义WKWebView
      _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
      //设置代理
      _webView.UIDelegate = self;
      _webView.navigationDelegate = self;

    //拼接访问地址
    NSString *urlString = "自己的url";
    

    // NSString *urlString = [baseUrl stringByAppendingString:@"JIRA/test.jsp"];
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
    //设置请求头
    [request setValue:cookieValue forHTTPHeaderField:@"Cookie"];
    //设置cookie
    // NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
    // request.allHTTPHeaderFields = requestHeaderFields;
    //设置post请求
    // [request setHTTPMethod:@"POST"];
    //加载后台页面
    [_webView loadRequest:request];

    //将导航栏设置为透明
    self.navigationController.navigationBar.translucent = YES;
    [self.view addSubview:_webView];
    //重写返回按钮
    self.navigationItem.leftBarButtonItem = self.backItem;
    

    }

    /**

    *重写返回按钮,可以是页面返回上一页

    */
    -(UIBarButtonItem *)backItem{

    if (!self.backItem0) {
        UIButton *back = [UIButton buttonWithType:UIButtonTypeSystem];
        [back setImage:[UIImage imageNamed:@"backIcon"] forState:UIControlStateNormal];
        //        [back setTitle:@"Back" forState:UIControlStateNormal];
        back.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        back.titleLabel.font = [UIFont systemFontOfSize:17];
        back.frame = CGRectMake(0, 0, 44, 32);
        [back addTarget:self action:@selector(back) forControlEvents:UIControlEventAllEvents];
        self.backItem0 = [[UIBarButtonItem alloc] initWithCustomView:back];
       
    }
    
    return self.backItem0;
    

    }

    -(void)back{
    [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(toDoSomeThing: ) object:self.btn];

    [self performSelector:@selector(toDoSomeThing:) withObject:self.btn afterDelay:0.8f];
    

    }

    -(void)toDoSomeThing:(UIViewController *)vc{

    if ([self.webView canGoBack]) {
        
        AppDelegate * appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
                        appDelegate.allowRotation = NO;//关闭横屏仅允许竖屏
        //切换到竖屏
        [UIDevice switchNewOrientation:UIInterfaceOrientationPortrait];
        [self.webView goBack];
        
    }else{
        
        AppDelegate * appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
        appDelegate.allowRotation = NO;//关闭横屏仅允许竖屏
        //切换到竖屏
        [UIDevice switchNewOrientation:UIInterfaceOrientationPortrait];
        
        [self.view resignFirstResponder];
        //返回主菜单原生页面的时候导航栏设置为不透明
        self.navigationController.navigationBar.translucent = NO;
        [self.navigationController popViewControllerAnimated:YES];
    }
    

    }

    //解决页面第一访问后cookie丢失问题

    • (void)webView:(WKWebView)webView decidePolicyForNavigationResponse:(WKNavigationResponse)navigationResponse decisionHandler:(void(^)(WKNavigationResponsePolicy))decisionHandler{

      NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;

      if (@available(iOS 11.0, *)) {
      WKHTTPCookieStore *cookieStroe = webView.configuration.websiteDataStore.httpCookieStore;
      for(NSHTTPCookie *cookie in cookies) {
      [cookieStroe setCookie:cookie completionHandler:nil];
      }
      }

      decisionHandler(WKNavigationResponsePolicyAllow);

    }

    pragma mark - WKNavigationDelegate

    // 页面开始加载时调用

    • (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{

      if (self.loadingAlert==nil){
      self.loadingAlert = [[UIAlertView alloc] initWithTitle:nil
      message: @"正在加载数据,请稍候....."
      delegate: self
      cancelButtonTitle: nil
      otherButtonTitles: nil];
      UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
      activityView.frame = CGRectMake(120.f, 48.0f, 37.0f, 37.0f);
      [self.loadingAlert addSubview:activityView];
      [activityView startAnimating];
      [self.loadingAlert show];
      }

    }

    // 当内容开始返回时调用

    • (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{

    }
    // 页面加载完成之后调用

    • (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{

      [self.loadingAlert dismissWithClickedButtonIndex:0 animated:YES];

    }

    //页面加载失败时调用

    • (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
      {
      NSLog(@"加载失败%@", error.userInfo);
      }

    // 接收到服务器跳转请求之后调用

    • (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{

    }

    /**

    *自建证书没有得到认证,访问https时需要强制信任证书,不知道我理解的有没有错
    */

    • (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *_Nullable))completionHandler
      {
      // NSLog(@"=====证书pppp=======");
      if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
      if (challenge.previousFailureCount == 0) {
      NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
      completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
      } else {
      completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
      }
      }
      }

    /**

    • 将用户名和密码放到浏览器缓存里,这个是不需要的,懒得该

    */

    • (NSString *)getUserName {

      return uname;
      }

    • (NSString *)getUserSP {

    return usersp01;
    

    }

    /**

    • web界面中有弹出警告框时调用
    • @param webView 实现该代理的webview
    • @param message 警告框中的内容
    • @param completionHandler 警告框消失调用
      */
    • (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
      //将本地加载等待弹框清除
      [self.loadingAlert dismissWithClickedButtonIndex:0 animated:YES];

      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

        if([message isEqualToString:@"用户信息过期,请重新登录!"]){
            LogInViewController *loginVC = [[LogInViewController alloc] init];
      
            AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
            IdleWindow *idleWindow = (IdleWindow *)delegate.window; //这个是我写的记录手机时间超时的
      

    // [[[NSURLCache alloc] init] removeAllCachedResponses]; //清除NSURLCache的缓存
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
    [loginVC clearCookiesForWkWebView];
    [idleWindow setRootViewController:loginVC];
    }
    completionHandler();
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
    }

    /**

    • 清除WKWebView 的cookie
      */
      -(void)clearCookiesForWkWebView{

      if([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0 ){
      NSArray *types = @[WKWebsiteDataTypeCookies,WKWebsiteDataTypeSessionStorage];
      NSSet *websiteDataTypes = [NSSet setWithArray:types];
      NSDate *dateformter = [NSDate dateWithTimeIntervalSince1970:0];
      [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateformter completionHandler:^{

       }];
      

      }else{
      NSString *libaryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
      NSString *cookieFolderPath = [libaryPath stringByAppendingString:@"/Cookies"];
      NSError *errors;
      [[NSFileManager defaultManager] removeItemAtPath:cookieFolderPath error:&errors];
      }
      }

    // 确认框
    //JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去

    • (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addAction:([UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
      completionHandler(NO);
      }])];
      [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
      completionHandler(YES);
      }])];
      [self presentViewController:alertController animated:YES completion:nil];
      }

    // 输入框
    //JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入

    • (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:prompt message:@"" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
      textField.text = defaultText;
      }];
      [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
      completionHandler(alertController.textFields[0].text?:@"");
      }])];
      [self presentViewController:alertController animated:YES completion:nil];
      }

    // 页面是弹出窗口 _blank 处理

    • (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
      if (!navigationAction.targetFrame.isMainFrame) {
      [webView loadRequest:navigationAction.request];
      }
      return nil;
      }

    @end

    @implementation WeakScriptMessageDelegate

    • (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)delegate {
      self = [super init];
      if (self) {
      _delegate = delegate;
      }
      return self;
      }

    • (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {

      if (self.delegate && [self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
      [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
      }
      }

    @end

    相关文章

      网友评论

          本文标题:WKWebView 使用

          本文链接:https://www.haomeiwen.com/subject/sewdbktx.html