美文网首页
wkwebview的监听方法

wkwebview的监听方法

作者: 马铃薯蜀黍 | 来源:发表于2023-07-14 11:42 被阅读0次

    简单使用
    1.加载网页
    与UIWebview一样,仅需三步:记住导入(#import <WebKit/WebKit.h>)

    // 加载网页

    • (void)loadWbView {
      // 1.创建webView,并设置大小,“80”为状态栏高度
      self.webVIew = [[WKWebView alloc] initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height - 80)];
      // 2.创建请求
      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://time.geekbang.org/"]];
      // 3.加载页面
      [self.webVIew loadRequest:request];
      [self.view addSubview:self.webVIew];
      }
    1. 加载本地文件
      // 加载本地文件
    • (void)loadLocalFile {
      // 1.创建webView,并设置大小,“80”为状态栏高度
      WKWebView *webVIew = [[WKWebView alloc] initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height - 80)];
      // 2.创建url
      NSURL *url = [NSURL fileURLWithPath:@"/Users/userName/Desktop/test.json/"];
      // 3.加载文件
      [webVIew loadFileURL:url allowingReadAccessToURL:url];
      [self.view addSubview:webVIew];
      }

    3.三个加载函数
    /// 加载网页

    • (WKNavigation *)loadRequest:(NSURLRequest *)request;
      // 加载HTML文件
    • (WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
      // 加载data数据
    • (WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL;

    4.WKwebView基本方法
    // 刷新

    • (void)reload;
      // 停止加载
    • (void)stopLoading;
      // 后退函数
    • (void)goBack;
      // 前进函数
    • (void)goForward;
      // 是否可以后退
      @property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
      // 是否可以向前
      @property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
      // 是否正在加载
      @property (nonatomic, readonly, getter=isLoading) BOOL loading;
      //会比较网络数据是否有变化,没有变化则使用缓存,否则从新请求
    • (WKNavigation *)reloadFromOrigin; // 增加的函数
      // 比向前向后更强大,可以跳转到某个指定历史页面
    • (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; //

    5.一些常用属性
    allowsBackForwardNavigationGestures:BOOL类型,是否允许左右划手势导航,默认不允许
    estimatedProgress:加载进度,取值范围0~1
    title:页面title
    .scrollView.scrollEnabled:是否允许上下滚动,默认允许
    backForwardList:WKBackForwardList类型,访问历史列表,可以通过前进后退按钮访问,或者通过goToBackForwardListItem函数跳到指定页面
    WKWebView涉及的代理方法

    // 页面开始加载时调用
    
    • (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
      }
      // 页面加载失败时调用
    • (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error {

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

    • (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
      }
      // 页面加载完成之后调用
    • (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
      [self getCookie];
      }
      //提交发生错误时调用
    • (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {

    }
    // 接收到服务器跳转请求即服务重定向时之后调用

    • (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
      }
      // 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转

    • (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

      NSString * urlStr = navigationAction.request.URL.absoluteString;
      NSLog(@"发送跳转请求:%@",urlStr);
      //自己定义的协议头
      NSString *htmlHeadString = @"github://";
      if([urlStr hasPrefix:htmlHeadString]){
      UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"通过截取URL调用OC" message:@"你想前往我的Github主页?" preferredStyle:UIAlertControllerStyleAlert];
      [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
      }])];
      [alertController addAction:([UIAlertAction actionWithTitle:@"打开" style:UIAlertActionStyleDefault handler:^(UIAlertAction * Nonnull action) {
      NSURL * url = [NSURL URLWithString:[urlStr stringByReplacingOccurrencesOfString:@"github://callName
      ?" withString:@""]];
      [[UIApplication sharedApplication] openURL:url];
      }])];
      [self presentViewController:alertController animated:YES completion:nil];
      decisionHandler(WKNavigationActionPolicyCancel);
      }else{
      decisionHandler(WKNavigationActionPolicyAllow);
      }
      }

      // 根据客户端受到的服务器响应头以及response相关信息来决定是否可以跳转

    • (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
      NSString * urlStr = navigationResponse.response.URL.absoluteString;
      NSLog(@"当前跳转地址:%@",urlStr);
      //允许跳转
      decisionHandler(WKNavigationResponsePolicyAllow);
      //不允许跳转
      //decisionHandler(WKNavigationResponsePolicyCancel);
      }
      //需要响应身份验证时调用 同样在block中需要传入用户身份凭证

    • (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
      //用户身份信息
      NSURLCredential * newCred = [[NSURLCredential alloc] initWithUser:@"user123" password:@"123" persistence:NSURLCredentialPersistenceNone];
      //为 challenge 的发送方提供 credential
      [challenge.sender useCredential:newCred forAuthenticationChallenge:challenge];
      completionHandler(NSURLSessionAuthChallengeUseCredential,newCred);
      }
      //进程被终止时调用

    • (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
      }

    WKWebView中的KVO举例(观察者模式)
    1.注册监听者
    要让一个对象监听另一个对象的属性的变化,首先需要将这个对象注册为相关属性的观察者,我们可以使用以下方法来实现:

    • (void)addObserver:(NSObject *)anObserver
      forKeyPath:(NSString *)keyPath
      options:(NSKeyValueObservingOptions)options
      context:(void *)context

    anObserver:观察者对象,这个对象必须实现observeValueForKeyPath:ofObject:change:context:方法,以响应属性的修改通知。
    keyPath:被监听的属性。这个值不能为nil。
    options:监听选项,这个值可以是NSKeyValueObservingOptions选项的组合。关于监听选项,我们会在下面介绍。
    context:任意的额外数据,我们可以将这些数据作为上下文数据,它会传递给观察者对象的observeValueForKeyPath:ofObject:change:context:方法。这个参数的意义在于用于区分同一对象监听同一属性(从属于同一对象)的多个不同的监听。我们将在下面看到。

    监听的四种类型

    typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
    // 提供属性的新值
    NSKeyValueObservingOptionNew = 0x01,
    // 提供属性的旧值
    NSKeyValueObservingOptionOld = 0x02,
    // 如果指定,则在添加观察者的时候立即发送一个通知给观察者,
    // 并且是在注册观察者方法返回之前
    NSKeyValueObservingOptionInitial = 0x04,
    // 如果指定,则在每次修改属性时,会在修改通知被发送之前预先发送一条通知给观察者,
    // 这与-willChangeValueForKey:被触发的时间是相对应的。
    // 这样,在每次修改属性时,实际上是会发送两条通知。
    NSKeyValueObservingOptionPrior = 0x08

    在添加观察者时还有两点需要注意的是:

    调用这个方法时,两个对象(即观察者对象及属性所属的对象)都不会被retain。
    可以多次调用这个方法,将同一个对象注册为同一属性的观察者(所有参数可以完全相同)。这时,即便在所有参数一致的情况下,新注册的观察者并不会替换原来观察者,而是会并存。这样,当属性被修改时,两次监听都会响应。
    举例:创建WkWebView并注册添加观察者

    self.webVIew = [[WKWebView alloc] initWithFrame:CGRectMake(0, 80, self.view.frame.size.width,   self.view.frame.size.height - 80)];
    // 2.创建请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://time.geekbang.org/"]];
    // 3.加载页面
    [self.webVIew loadRequest:request];
    self.webVIew.navigationDelegate = self;
    // 给webView 添加一个监听者(self),监听的为estimatedProgress属性有新变化的时候(NSKeyValueObservingOptionNew)
    

    //添加监测网页加载进度的观察者
    [self.webView addObserver:self
    forKeyPath:@"estimatedProgress"
    options:NSKeyValueObservingOptionNew
    context:nil];
    //添加监测网页标题title的观察者
    [self.webView addObserver:self
    forKeyPath:@"title"
    options:NSKeyValueObservingOptionNew
    context:nil];

    };

    2.添加监听的回调方法
    当被监听的属性修改时,KVO会发出一个通知以告知所有监听这个属性的观察者对象。而观察者对象必须实现 -observeValueForKeyPath:ofObject:change:context:方法,来对属性修改通知做相应的处理。这个方法的声明如下:

    • (void)observeValueForKeyPath:(NSString *)keyPath
      ofObject:(id)object
      change:(NSDictionary *)change
      context:(void *)context

    参数说明:

    keyPath:即被观察的属性,与参数object相关。
    object:keyPath所属的对象。
    change:这是一个字典,它包含了属性被修改的一些信息。这个字典中包含的值会根据我们在添加观察者时设置的options参数的不同而有所不同。
    context:这个值即是添加观察者时提供的上下文信息。
    对于第三个参数,我们通常称之为变化字典(Change Dictionary),它记录了被监听属性的变化情况。
    与注册时的options 选项的参数一一对应。
    我们可以通过以下key来获取我们想要的信息:

    // 属性变化的类型,是一个NSNumber对象,包含NSKeyValueChange枚举相关的值
    NSString *const NSKeyValueChangeKindKey;

    // 属性的新值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
    // 且添加观察的方法设置了NSKeyValueObservingOptionNew时,我们能获取到属性的新值。
    // 如果NSKeyValueChangeKindKey是NSKeyValueChangeInsertion或者NSKeyValueChangeReplacement,
    // 且指定了NSKeyValueObservingOptionNew时,则我们能获取到一个NSArray对象,包含被插入的对象或
    // 用于替换其它对象的对象。
    NSString *const NSKeyValueChangeNewKey;

    // 属性的旧值。当NSKeyValueChangeKindKey是 NSKeyValueChangeSetting,
    // 且添加观察的方法设置了NSKeyValueObservingOptionOld时,我们能获取到属性的旧值。
    // 如果NSKeyValueChangeKindKey是NSKeyValueChangeRemoval或者NSKeyValueChangeReplacement,
    // 且指定了NSKeyValueObservingOptionOld时,则我们能获取到一个NSArray对象,包含被移除的对象或
    // 被替换的对象。
    NSString *const NSKeyValueChangeOldKey;

    // 如果NSKeyValueChangeKindKey的值是NSKeyValueChangeInsertion、NSKeyValueChangeRemoval
    // 或者NSKeyValueChangeReplacement,则这个key对应的值是一个NSIndexSet对象,
    // 包含了被插入、移除或替换的对象的索引
    NSString *const NSKeyValueChangeIndexesKey;

    // 当指定了NSKeyValueObservingOptionPrior选项时,在属性被修改的通知发送前,
    // 会先发送一条通知给观察者。我们可以使用NSKeyValueChangeNotificationIsPriorKey
    // 来获取到通知是否是预先发送的,如果是,获取到的值总是@(YES)
    NSString *const NSKeyValueChangeNotificationIsPriorKey;

    其中,NSKeyValueChangeKindKey的值取自于NSKeyValueChange,它的值是由以下枚举定义的:

    enum {

    // 设置一个新值。被监听的属性可以是一个对象,也可以是一对一关系的属性或一对多关系的属性。
    NSKeyValueChangeSetting = 1,
    
    // 表示一个对象被插入到一对多关系的属性。
    NSKeyValueChangeInsertion = 2,
    
    // 表示一个对象被从一对多关系的属性中移除。
    NSKeyValueChangeRemoval = 3,
    
    // 表示一个对象在一对多的关系的属性中被替换
    NSKeyValueChangeReplacement = 4
    

    };
    typedef NSUInteger NSKeyValueChange;

    以下这个例子中 chang 的内容为:

    {
    kind = 1; // 对应上面 NSKeyValueChangeSetting
    new = "0.5"; // 表示当前的进度为0.5
    }

    举例:

    pragma mark kvo 监听进度 必须实现此方法 监听的回调

    -(void)observeValueForKeyPath:(NSString *)keyPath
    ofObject:(id)object
    change:(NSDictionary<NSKeyValueChangeKey,id> *)change
    context:(void *)context{
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))]
    && object == _webView) {
    NSLog(@"网页加载进度 = %f",_webView.estimatedProgress);
    self.progressView.progress = _webView.estimatedProgress;
    if (_webView.estimatedProgress >= 1.0f) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.progressView.progress = 0;
    });
    }
    }else if([keyPath isEqualToString:@"title"]
    && object == _webView){
    self.navigationItem.title = _webView.title;
    }else{
    [super observeValueForKeyPath:keyPath
    ofObject:object
    change:change
    context:context];
    }
    }

    3.移除监听
    移除监听的方法有两种:

    • (void)removeObserver:(NSObject *)anObserver
      forKeyPath:(NSString *)keyPath

    • (void)removeObserver:(NSObject *)observer
      forKeyPath:(NSString *)keyPath
      context:(void *)context

    需要在dealloc中调用

    • (void)dealloc {
      // 移除监听
      [self.webVIew removeObserver:self forKeyPath:@"estimatedProgress"];
      }
      ————————————————
      版权声明:本文为CSDN博主「liudongshizhang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
      原文链接:https://blog.csdn.net/liudongshizhang/article/details/117357476

    相关文章

      网友评论

          本文标题:wkwebview的监听方法

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