J'essaie d'implémenter Estimated Progress
dans mon WKWebView
mais je n'arrive pas à le comprendre. Pouvez-vous m'aider?
Voici ce que j'ai:
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];
Je vois que cette réponse y arrive un peu, mais c'est pour un spinner: IWebView avec barre de progression
Et Apple documente une sorte de estimatedProgress
(je suppose que c'est la fine barre bleue juste en dessous de la barre de navigation qui montre la progression comme dans Safari) mais je ne vois généralement pas comment cela serait mis en œuvre: https://developer.Apple.com/library/ios/documentation/WebKit/Reference/WKWebView_Ref/#//Apple_ref/occ/instp/WKWebView/estimatedProgress
Je suis donc coincé ici. Toute aide serait appréciée Merci!
[~ # ~] mise à jour [~ # ~] : C'est ce que j'ai en ce moment. Obtenir un plantage car il semble que ma vue de progression et WKWebView se chargent deux fois, et je ne sais pas pourquoi. Obtenir une erreur que l'observateur doit être supprimé. Voici mon code tel qu'il 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];
}
}
MISE À JOUR: En utilisant les CocoaPods, c'est ce que j'ai, mais il affiche deux vues au lieu d'une seule vue 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];
}
Vérifiez KINWebBrowser sur GitHub pour voir une implémentation complète de la solution ci-dessous.
Si vous regardez attentivement la documentation de la propriété estimatedProgress
de WKWebView
que vous avez liée, vous verrez:
The WKWebView class is key-value observing (KVO) compliant for this property.
Cela signifie que vous pouvez configurer l'observation de la valeur de clé sur la propriété estimatedProgress
pour observer les modifications apportées à sa valeur. À partir de la méthode observeValueForKeyPath
, vous pouvez mettre à jour votre interface utilisateur.
Le motif de conception KVO en cacao est assez désordonné. Consultez cet excellent article NSHipster sur les meilleures pratiques de Key Value Observing .
Voici l'implémentation KVO pour estimatedProgress
sur WKWebView
:
Depuis votre UIViewController
, configurez votre WKWebView
et ajoutez-vous en tant qu'observateur 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];
Dans le même UIViewController
configurez votre méthode observeValueForKeyPath
pour filtrer la propriété estimatedProgress
de webView
. Vous pouvez ensuite accéder directement à la valeur estimatedProgress
et mettre à jour votre interface utilisateur en conséquence.
- (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];
}
}
Assurez-vous de supprimer KVO du UIViewController
dans la méthode dealloc de ce UIViewController. Il est important de vérifier si isViewLoaded
pour éviter un plantage si l'observateur n'a pas déjà été ajouté.
- (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];
}
Pour voir cela en action sur certains gros fichiers, chargez un énorme fichier image de cette douce galaxie. (Ce fichier fait 35 Mo. Assurez-vous que vous êtes en WiFi!)
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.spacetelescope.org/static/archives/images/large/opo0328a.jpg"]];
[self.webView loadRequest:URLRequest];
Si vous utilisez un UIProgressView
, vous pouvez réaliser un safari comme un effet de fondu avec ce code:
- (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)
}
}
Mise à jour 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
Swift 3.2 et supérieur:
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)
}
}