美文网首页
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