ios WKWebView 估计进度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26198334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WKWebView Estimated Progress
提问by Realinstomp
I'm trying to implement Estimated Progress
in my WKWebView
but can't seem to figure it out. Can you help?
我试图Estimated Progress
在我的WKWebView
但似乎无法弄清楚。你能帮我吗?
Here's what I've got:
这是我所拥有的:
self.view = self.webView;
NSURL *url = [NSURL URLWithString:stringWeb];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
[self.webView loadRequest:request];
I see this answer gets at it a bit, but thats for a spinner: UIWebView with Progress Bar
我看到这个答案有点意思,但那是一个微调器:UIWebView with Progress Bar
And Apple documents some sort of estimatedProgress
(I'm assuming its the thin blue bar right below the navigation bar that shows progress like in Safari) but I don't see generally how that would be implemented: https://developer.apple.com/library/ios/documentation/WebKit/Reference/WKWebView_Ref/#//apple_ref/occ/instp/WKWebView/estimatedProgress
Apple 记录了某种形式estimatedProgress
(我假设它的导航栏正下方的蓝色细条显示 Safari 中的进度),但我通常看不到它是如何实现的:https: //developer.apple.com /library/ios/documentation/WebKit/Reference/WKWebView_Ref/#//apple_ref/occ/instp/WKWebView/estimatedProgress
So I'm stuck here. Any help would be appreciated, thanks!
所以我被困在这里。任何帮助将不胜感激,谢谢!
UPDATE: This is what I have right now. Getting a crash because it looks like my Progress View and WKWebView are loading twice, and I'm not sure why that would be. Getting an error that observer needs to be removed. Here's my code as it stands-
更新:这就是我现在所拥有的。崩溃是因为看起来我的 Progress View 和 WKWebView 加载了两次,我不确定为什么会这样。收到需要删除观察者的错误。这是我的代码 -
ViewController.h
视图控制器.h
@interface WebPageViewController : UIViewController <UIWebViewDelegate>
@property (strong, nonatomic) NSString *stringMobile;
@property (strong, nonatomic) NSString *stringWeb;
@property (strong, nonatomic) IBOutlet UIView *view;
@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic) UIProgressView *progressView;
ViewController.m
视图控制器.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
[self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.center = self.view.center;
[self.view addSubview:self.progressView];
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:stringWeb]];
[self.webView loadRequest:URLRequest];
}
- (void)dealloc {
[self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
// if you have set either WKWebView delegate also set these to nil here
[self.webView setNavigationDelegate:nil];
[self.webView setUIDelegate:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"] && object == self.webView) {
[self.progressView setAlpha:1.0f];
[self.progressView setProgress:self.webView.estimatedProgress animated:YES];
if(self.webView.estimatedProgress >= 1.0f) {
[UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.progressView setAlpha:0.0f];
} completion:^(BOOL finished) {
[self.progressView setProgress:0.0f animated:NO];
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
UPDATE: Using the CocoaPods this is what I have but its showing two Views instead of just one webview
更新:使用 CocoaPods 这就是我所拥有的,但它显示了两个视图而不是一个 web 视图
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *myURL = [NSURL URLWithString: [self.url stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:myURL];
//[self.webView loadRequest:request];
// KIN
// Deleted UIWebView in Storyboard
KINWebBrowserViewController *webBrowser = [[KINWebBrowserViewController alloc] init];
[self.navigationController pushViewController:webBrowser animated:YES];
[webBrowser loadURL:myURL];
}
回答by dfmuir
Check KINWebBrowseron GitHub to see a full implementation of the solution below.
检查GitHub 上的KINWebBrowser以查看以下解决方案的完整实现。
If you look closely at the documentation for the estimatedProgress
property of WKWebView
that you linked to you will see:
如果您仔细查看链接到的estimatedProgress
属性的文档,WKWebView
您将看到:
The WKWebView class is key-value observing (KVO) compliant for this property.
This means that you can set up key value observing on the estimatedProgress
property to observe changes to it's value. From the observeValueForKeyPath
method you can update your UI.
这意味着您可以在estimatedProgress
属性上设置键值观察以观察其值的变化。通过该observeValueForKeyPath
方法,您可以更新您的 UI。
The KVO design pattern in Cocoa is pretty messy. Check out this excellent NSHipster article about the best practices of Key Value Observing.
Cocoa 中的 KVO 设计模式非常混乱。查看这篇关于关键值观察最佳实践的优秀 NSHipster 文章。
Here is the KVO implementation for estimatedProgress
on WKWebView
:
这是estimatedProgress
on的 KVO 实现WKWebView
:
From your UIViewController
, set up your WKWebView
and add self as an observer of estimatedProgress
从您的UIViewController
, 设置您WKWebView
并将自己添加为estimatedProgress
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
[self.webView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:NSKeyValueObservingOptionNew context:NULL];
In the same UIViewController
set up your observeValueForKeyPath
method to filter out the estimatedProgress
property of webView
. You can then access the estimatedProgress
value directly and update your UI accordingly.
在相同的UIViewController
设置你的observeValueForKeyPath
方法来过滤掉estimatedProgress
的财产webView
。然后,您可以estimatedProgress
直接访问该值并相应地更新您的 UI。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.webView) {
NSLog(@"%f", self.webView.estimatedProgress);
// estimatedProgress is a value from 0.0 to 1.0
// Update your UI here accordingly
}
else {
// Make sure to call the superclass's implementation in the else block in case it is also implementing KVO
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
Make sure to remove KVO from the UIViewController
in the dealloc method of that UIViewController. It is important to check if isViewLoaded
to avoid a crash if the observer has not already been added.
确保从该UIViewController
UIViewController 的 dealloc 方法中删除 KVO 。如果isViewLoaded
尚未添加观察者,检查是否避免崩溃很重要。
- (void)dealloc {
if ([self isViewLoaded]) {
[self.wkWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
}
// if you have set either WKWebView delegate also set these to nil here
[self.wkWebView setNavigationDelegate:nil];
[self.wkWebView setUIDelegate:nil];
}
To see this in action on some large files load a huge image file of this sweet galaxy. (This file is 35MB. Make sure you are on WiFi!)
要在一些大文件上看到这一点,请加载这个甜蜜星系的巨大图像文件。(此文件为 35MB。请确保您使用的是 WiFi!)
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.spacetelescope.org/static/archives/images/large/opo0328a.jpg"]];
[self.webView loadRequest:URLRequest];
If you are using a UIProgressView
you can achieve a safari like fade-out effect with this code:
如果您使用的是UIProgressView
,则可以使用以下代码实现类似淡出效果的 safari:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.wkWebView) {
[self.progressView setAlpha:1.0f];
[self.progressView setProgress:self.wkWebView.estimatedProgress animated:YES];
if(self.wkWebView.estimatedProgress >= 1.0f) {
[UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.progressView setAlpha:0.0f];
} completion:^(BOOL finished) {
[self.progressView setProgress:0.0f animated:NO];
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
回答by Array
Swift-like:
像斯威夫特:
@IBOutlet weak var progressView: UIProgressView!
//...
func viewDidLoad() {
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil) // add observer for key path
}
// ...
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if (keyPath == "estimatedProgress") { // listen to changes and updated view
progressView.hidden = webView.estimatedProgress == 1
progressView.setProgress(Float(webView.estimatedProgress), animated: true)
}
}
Swift 3 update:
斯威夫特 3 更新:
// Add Observer in viewDidLoad
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
if (keyPath == "estimatedProgress") { // listen to changes and updated view
progress.isHidden = webView.estimatedProgress == 1
progress.setProgress(Float(webView.estimatedProgress), animated: false)
}
}
Also please make sure to implement "WKNavigationDelegate" and add webview reference navigationDelegate to self like below
webView.navigationDelegate=self
回答by Vitalii
Swift 3.2and higher:
Swift 3.2及更高版本:
private var progressKVOhandle: NSKeyValueObservation?
@IBOutlet weak var progressView: UIProgressView!
// ...
override func viewDidLoad() {
super.viewDidLoad()
// ...
progressKVOhandle = webView.observe(\.estimatedProgress) { [weak self] (object, _) in
self?.progressView.setProgress(Float(object.estimatedProgress), animated: true)
}
}