web-dev-qa-db-fra.com

UIWebView avec barre de progression

Bonjour, je suis un débutant en programmation et j'essaye de créer ma première application pour iPhone sur Xcode . Mon application contient un bouton qui ouvre UIWebView lorsque vous appuyez dessus et charge une page d'accueil . Maintenant, je veux aussi pour ajouter une vue de progression à la vue Web que Safari utilise également, ce qui indique la progression du chargement de la page. Comment puis je faire ça?
Mon code pour charger l’URL dans le UIWebView:

.h

IBOutlet UIWebView *webView;

.m

- (void)viewDidLoad
{
[webView loadRequest:[NSURLRequest requestWithURL: [NSURL URLWithString:@"http:/www.google.com/"]]];

Merci de votre aide!

22
user3220034

Pour avoir une UIProgressView précise, vous devez avoir une tâche qui:

  • Vous pouvez obtenir des informations alors que ce n'est pas complet
  • Quantifier son "exhaustivité" en pourcentage basé sur cette information.

Maintenant, lorsque vous chargez votre UIWebView, c’est impossible. Et Apple ne le fait pas non plus. Apple utilise souvent de faux UIProgressViews pour vous donner quelque chose à regarder pendant le chargement de la page. Mail utilise également de fausses vues de progression. Allez l'essayer pour vous-même. Voici comment fonctionnent les fausses vues de progression d'Apple:

  • La vue de progression commence à se déplacer à un rythme lent et constant
  • Si la tâche se termine avant la fin de la barre, elle passe soudainement à 100% sur le reste, avant de disparaître.
  • Si la tâche prend beaucoup de temps, la vue de progression s'arrêtera à 95% et y restera jusqu'à la fin de la tâche.

Pour ce faire, vous devrez animer manuellement progressView. Vous pouvez le sous-classer mais ce serait probablement un peu avancé pour vous. Le moyen le plus simple serait ceci:

Dans myViewController.h

@interface myViewController : UIViewController {
     BOOL theBool;
     //IBOutlet means you can place the progressView in Interface Builder and connect it to your code
     IBOutlet UIProgressView* myProgressView;
     NSTimer *myTimer;
}
@end

Dans myViewController.m

#import "myViewController.h"
@implementation myViewController
- (void)webViewDidStartLoad:(UIWebView *)webView{
     myProgressView.progress = 0;
     theBool = false;
     //0.01667 is roughly 1/60, so it will update at 60 FPS
     myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01667 target:self selector:@selector(timerCallback) userInfo:nil repeats:YES];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
     theBool = true;
}
-(void)timerCallback {
    if (theBool) {
         if (myProgressView.progress >= 1) {
              myProgressView.hidden = true;
              [myTimer invalidate];
         }
         else {
              myProgressView.progress += 0.1;
         }
    }
    else {
         myProgressView.progress += 0.05;
         if (myProgressView.progress >= 0.95) {
              myProgressView.progress = 0.95;
         }
    }
}
@end

Ensuite, lorsque votre tâche sera terminée, définissez theBool = true; et la vue de progression se chargera de elle-même. Modifiez les valeurs dans l'instruction if pour contrôler la vitesse de l'animation.

70
WolfLink

Swift 2.2

class ViewController: UIViewController,UIWebViewDelegate {

    @IBOutlet weak var webView: UIWebView!
    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
    @IBOutlet weak var myProgressView: UIProgressView!

    var myTimer = NSTimer()
    var theBool = Bool()

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = NSURL(string: "https://www.youtube.com")
        let request = NSURLRequest(URL: url!)
        activityIndicator.hidesWhenStopped = true
        activityIndicator.startAnimating()
        webView.loadRequest(request)

    }
    func timerCallback(){
        if theBool {
            if myProgressView.progress >= 1 {
                myProgressView.hidden = true
                myTimer.invalidate()
            }else{
                myProgressView.progress += 0.1
            }
        }else{
            myProgressView.progress += 0.05
            if myProgressView.progress >= 0.95 {
                myProgressView.progress = 0.95
            }
        }
    }

    func webViewDidStartLoad(webView: UIWebView) {
        activityIndicator.startAnimating()
        myProgressView.progress = 0
        theBool = false
        myTimer =  NSTimer.scheduledTimerWithTimeInterval(0.01667,target: self,selector: #selector(ViewController.timerCallback),userInfo: nil,repeats: true)
    }
    func webViewDidFinishLoad(webView: UIWebView) {
        activityIndicator.stopAnimating()
        theBool = true
    }
}
5
ZAFAR007

Si quelqu'un veut le faire dans Swift 3, j'ai passé quelques jours à essayer de le comprendre et finalement je l'ai fait.

Voici le code :)

override func viewDidLoad() {
    super.viewDidLoad()

    let url = NSURL(string: "http://google.com")
    let request = NSURLRequest(url: url as! URL)
    webView.loadRequest(request as URLRequest)
    webView.delegate=self

}

func webViewDidStartLoad(_ webView: UIWebView) {

    self.progressView.setProgress(0.1, animated: false)
}


func webViewDidFinishLoad(_ webView: UIWebView) {

    self.progressView.setProgress(1.0, animated: true)
}

func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {

    self.progressView.setProgress(1.0, animated: true)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
3
Matej Marić

J'ai suivi la réponse de Wolflink et constaté que le même problème ne concernait pas ProgressView.

Après avoir lu la référence de classe NSTimer:

https://developer.Apple.com/library/Mac/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html#//Apple_ref/occ/clm/NSTimer/timerWithTimeIntervalInterval:target: sélecteur: userInfo: repeats :

Dans Discussion , vous pouvez lire: "Vous devez ajouter le nouveau temporisateur à une boucle d'exécution à l'aide de addTimer: forMode :."

alors j'ai ajouté

[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];

après

myTimer = [NSTimer timerWithTimeInterval:0.01667 target:self selector:@selector(timerCallback) userInfo:nil repeats:YES];

Cela a fonctionné pour moi (comme WolfLink m'a recommandé de faire la sous-classe UIProgressView)

3
danihvilla

C'est difficile (si possible), car il vous faudrait suivre toutes les ressources chargées sur le site, mais…

J'ai une idée. C'est plus un truc qu'une vraie solution, mais je pense que même Apple l'utilise dans l'application Messages :)

  1. Lorsque vous commencez à charger la page, commencez une animation à 90% de la progression (disons avec une durée de 1,5 seconde, peut-être différente pour le Wi-Fi, le LTE, la 3G,…).
  2. Lorsque la page se charge entre-temps, animez rapidement la progression à 100% . Terminé!
  3. Si le chargement de la page prend plus de temps, la barre de progression s’arrêtera à 90% et y attendra . Moment frustrant lorsque l'utilisateur regarde l'indicateur de rotation lente dans la barre d'état! Et enfin, le chargement de la page se termine et (comme au point 2.) vous jouez animation rapide à 100% . Terminé!

Je pense que nous savons tous que c'est comme ça que l'application Messages fonctionne, car je ne crois pas que l'envoi de messages SMS puisse être suivi avec une progression aussi précise :)

2
Tricertops

J'aurais ajouté un commentaire au lieu d'ajouter une réponse, mais je n'ai pas encore assez de réputation pour commenter!

Il y a quelques jours à peine, j'ai posé à peu près la même question. Dans cette question, j'ai inclus la solution que j'ai proposée. Ma solution est plus compliquée que celle de WolfLink, mais elle suit la progression réelle du chargement de la page, même si elle n’est pas précise à 100%. Comme WolfLink l'a dit, ce n'est pas possible. Ma question peut être trouvée ici: Barre de progression pour UIWebView

Notez que, quelle que soit la procédure choisie, vous devrez vérifier la propriété de chargement de UIWebView pour déterminer à quel moment le chargement de la page est terminé.

0
Stuart Fisher

Apple fournit désormais le framework WebKit, qui inclut la classe WKWebView, qui vous permet d’interroger la progression estimée à l’aide de la propriété "EstiméProgress". Vous ne devez donc plus "simuler" la progression comme vous le feriez pour afficher une barre de progression sur UIWebView.

0
Patrick T Nelson