Progreso estimado de WKWebView

Estoy intentando implementar el Estimated Progress en mi WKWebView pero no puedo resolverlo. ¿Puede usted ayudar?

Esto es lo que tengo:

 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]; 

Veo que esta respuesta llega un poco, pero eso es para un spinner: UIWebView con Progress Bar

Y Apple documenta algún tipo de estimatedProgress (supongo que es la delgada barra azul justo debajo de la barra de navigation que muestra el progreso como en Safari), pero no veo generalmente cómo se implementaría: https://developer.apple. com / library / ios / documentation / WebKit / Reference / WKWebView_Ref / # // apple_ref / occ / instp / WKWebView / estimatedProgress

Entonces estoy atrapado aquí. ¡Cualquier ayuda será apreciada, gracias!

ACTUALIZACIÓN : esto es lo que tengo ahora mismo. Caer un crash porque parece que mi vista de progreso y WKWebView se están cargando dos veces, y no estoy seguro de por qué eso sería. Obteniendo un error que necesita remover al observador. Aquí está mi código tal como está:

ViewController.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

 - (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]; } } 

ACTUALIZACIÓN: Usando CocoaPods, esto es lo que tengo, pero muestra dos vistas en lugar de una sola vista 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]; } 

Verifique KINWebBrowser en GitHub para ver una implementación completa de la solución a continuación.

Si observa detenidamente la documentation de la propiedad estimatedProgress de WKWebView que ha vinculado, verá:

 The WKWebView class is key-value observing (KVO) compliant for this property. 

Esto significa que puede configurar la observación del valor key en la propiedad estimatedProgress para observar los cambios en su valor. Desde el método observeValueForKeyPath puede actualizar su UI.

El patrón de layout de KVO en Cocoa es bastante complicado. Consulte este excelente artículo de NSHipster sobre las mejores prácticas de Key Value Observing .

Aquí está la implementación de KVO para estimatedProgress en WKWebView :

Desde su UIViewController , configure su WKWebView y agregue uno mismo como un observador de 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]; 

En el mismo UIViewController configure su método observeValueForKeyPath para filtrar la propiedad estimatedProgress de webView . A continuación, puede acceder al valor estimatedProgress directamente y actualizar su UI en consecuencia.

 - (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]; } } 

Asegúrese de eliminar KVO del UIViewController en el método dealloc de ese UIViewController. Es importante verificar si isViewLoaded para evitar un locking si el observador aún no se ha agregado.

 - (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]; } 

Para ver esto en acción en algunos files grandes, cargue un file de image enorme de esta dulce galaxia. (Este file es de 35 MB. ¡Asegúrese de estar en WiFi!)

  NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.spacetelescope.org/static/archiveshttp://iosberry.comlarge/opo0328a.jpg"]]; [self.webView loadRequest:URLRequest]; 

Si está utilizando un UIProgressView , puede lograr un efecto de safari como el efecto de desvanecimiento con este código:

 - (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]; } } 

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) } } 

Actualización Swift 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