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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:01:22  来源:igfitidea点击:

WKWebView Estimated Progress

ioswebviewuiwebviewwkwebview

提问by Realinstomp

I'm trying to implement Estimated Progressin my WKWebViewbut 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 estimatedProgressproperty of WKWebViewthat 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 estimatedProgressproperty to observe changes to it's value. From the observeValueForKeyPathmethod 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 estimatedProgresson WKWebView:

这是estimatedProgresson的 KVO 实现WKWebView

From your UIViewController, set up your WKWebViewand 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 UIViewControllerset up your observeValueForKeyPathmethod to filter out the estimatedProgressproperty of webView. You can then access the estimatedProgressvalue 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 UIViewControllerin the dealloc method of that UIViewController. It is important to check if isViewLoadedto avoid a crash if the observer has not already been added.

确保从该UIViewControllerUIViewController 的 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 UIProgressViewyou 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)
    }
}