1

I am using the below to add a ProgressView while the UIWebView is loading and dismissing it when it's done. The problem is the UIWebView is started twice and also the ProgressView, So when the page is done loading only one ProgressView is dismissed and the other one doesn't.

ViewController.h

#import <UIKit/UIKit.h>

@interface DirectionViewController : UIViewController <UIWebViewDelegate>
   @property (weak, nonatomic) IBOutlet UIWebView *directionWebView;
@end

ViewController.m

@interface ViewController () 
    @property UIColor *yellowColor;
    @property MRProgressOverlayView *progressView;
@end

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.yellowColor =
    [UIColor colorWithRed:244.0f/255.0f
                    green:208.0f/255.0f
                     blue:63.0f/255.0f
                    alpha:1.0f];
    self.directionWebView.delegate = self;
    NSString *urlMap = [NSString stringWithFormat:@"%@%f,%f&zoom=14", @"http://maps.google.com/maps?q=", self.coordLat, self.coordLong];
    NSURL *url = [NSURL URLWithString:urlMap];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    [self.directionWebView loadRequest:urlRequest];
}

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSLog(@"WebView start loading...");
    self.progressView = [MRProgressOverlayView new];
    self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
    [self.view.window addSubview:self.progressView];
    [self.progressView setTintColor:self.yellowColor];
    [self.progressView setTitleLabelText:@"Loading ..."];
    [self.progressView show:YES];
    return YES;
}

-(void)webViewDidFinishLoad:(UIWebView *)webView
{
     [self.progressView dismiss:YES];
}
@end
Haroun SMIDA
  • 1,106
  • 3
  • 16
  • 32

3 Answers3

1

Dont know why it is calling twice but you can do this.

if(!self.progressView){
self.progressView = [MRProgressOverlayView new];
    self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
    [self.view.window addSubview:self.progressView];
    [self.progressView setTintColor:self.yellowColor];
    [self.progressView setTitleLabelText:@"Loading ..."];
    [self.progressView show:YES];
}

-(void)webViewDidFinishLoad:(UIWebView *)webView
{
     [self.progressView dismiss:YES];
self.progressView  = nil;
}
KDeogharkar
  • 10,939
  • 7
  • 51
  • 95
1
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

This delegate method can be called multiple times (in case of redirection for example). So I would recommend to move your Progress view init code to viewDidLoad method.

- (void)viewDidLoad {
    [super viewDidLoad];
    //...
    self.progressView = [MRProgressOverlayView new];
    self.progressView.mode = MRProgressOverlayViewModeIndeterminateSmall;
    [self.view.window addSubview:self.progressView];
    [self.progressView setTintColor:self.yellowColor];
    [self.progressView setTitleLabelText:@"Loading ..."];
}

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSLog(@"WebView start loading...");
    [self.progressView show:YES];
    return YES;
}

-(void)webViewDidFinishLoad:(UIWebView *)webView {
    [self.progressView dismiss:YES];
}
Igor Kulagin
  • 1,701
  • 15
  • 20
1
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

it may be triggered more than once, e.g redirects, iframe loading and so on. It's very inconvenient to initialise objects here.

Use Lazy Initialization design pattern for it

- (MRProgressOverlayView *)progressView {
    if (_progressView) {
        _progressView = [... alloc] init];
        // ... setup your progressView
    }
    return _progressView;
}

btw, you forgot about error handling:

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    // You need to stop loading indicator here, right?!
}

Second thing is - (maybe for you case it's not a big deal) but usually it's tricky to exactly determine when UIWebView stopped loading (all the resources loaded, AJAX requests and so on)

Personally I'm using something like code below to manage activity indicator start/stop behaviour for UIWebView

#pragma mark UIWebViewDelegate

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
 navigationType:(UIWebViewNavigationType)navigationType
{
    NSLog(@"Webview (%p) starting to load URL: %@", self, request.URL);
    self.URL = request.URL;
    return YES;
}

- (void)webViewDidStartLoad:(UIWebView *)webView
{
    [self.spinner startAnimating];
    self.webViewLoadingCount++;
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.webViewLoadingCount--;
    if (self.webViewLoadingCount > 0) return;
    [self.spinner stopAnimating];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    self.webViewLoadingCount--;

    [self.spinner stopAnimating];

    // Ignore NSURLErrorDomain error (-999).
    if (error.code == NSURLErrorCancelled) return;

    // Ignore "Frame Load Interrupted" errors 
    if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return;

    NSLog(@"WebView (%p) experienced an error: %@.", self, [error localizedDescription]);
}
Injectios
  • 2,777
  • 1
  • 30
  • 50