WebKit; Automatically adding "http://" to URL, and Connection Errors?

Discussion in 'Mac Programming' started by Noisemaker, Dec 30, 2010.

  1. Noisemaker Guest

    Joined:
    Mar 13, 2009
    #1
    I'm working on an app that's making use of a URL Bar and WebView. It's all but done, however there are two things left to finish before it's user-ready.

    The first is that the address field requires the user to type in "http://" with their URL. It's not a big deal, but I would prefer to not require users to do so, as it could lead to confusion. How can I detect and automatically add "http://" to the URL text in the event that it's not present?

    Next, I want to add a connection error. In the event that the load request can't be completed, I want the user to know it - not just sit there watching the activity indicator spin. How can I add an error for a lack of internet connection?

    I'd appreciate any help on these issues!
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    Hi Noisemaker,

    I'm an experienced programmer but a novice at Cocoa, but perhaps I can help.

    From what I've read about detecting network connectivity, there seems to be 2 ways to do this.

    The first way is to have your view or window controller respond to the webView:didFailLoadWithError:forFrame: message of the WebFrameLoadDelegate protocol. And then assign your controller via WebView's setFrameLoadDelegate:. If there is any kind of failure while loading a web page, WebView will send this message to your controller.

    The second way is to proactively try and make a connection to a known good source (such as Google) by sending the sendSynchronousRequest:returnedResponse:error: message to the NSURLConnection class. If the result of this message is nil, there was a problem.

    In both methods, you can investigate the NSError object to find out more detail of why the request failed. Usually though, you'd just construct an NSAlert via alertWithError: and show the alert.

    In regards to adding a missing "http://", do you have the action from the URL Bar connect directly to the WebView's takeStringURLFrom:? If you do, might need to connect it instead to an IBAction method on your controller. In this method, you could query to URL string from the URL bar, check if it doesn't starts some other protocol follow by :// and if it doesn't then append http:// to the URL string before calling your WebView's setMainFrameURL: method.

    Hope some this might help. Happy coding, and happy New Year!

    Jim In Aus

    In regards to
     
  3. Noisemaker thread starter Guest

    Joined:
    Mar 13, 2009
    #3
    Thanks for the reply, Jiminaus!

    I actually just solved the http:// issue a bit ago in the exact method you described. I had it set up and connected directly to the WebView, and found that it was the problem - it's easy to set up, but a little extra work makes it better for the end user. It's sorted now, and is working perfectly!

    I'll look into the error methods you mentioned - hopefully I can get it sorted without too much issue here in a little bit!

    Thanks!
     
  4. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    Hi again Noisemaker,

    For my own learning, I went ahead and coded the following. The code is all in the controller.

    Note: I call the callback message wrong. It's the provisional one that get's called not the non-provisional one. I just implemented both.

    Code:
    - (void)awakeFromNib {
        BOOL connected = [self checkConnection];
        if (connected) {
            [self goToURL:self];
        }
    }
    
    
    - (IBAction)goToURL:(id)sender {
        NSString* urlString = self.urlField.stringValue;
    	
        NSURL* url = [NSURL URLWithString:urlString];
        if (![url scheme]) {
            urlString = [@"http://" stringByAppendingString:urlString];
    	self.urlField.stringValue = urlString;
    	url = [NSURL URLWithString:urlString];
        }
        NSURLRequest* req = [NSURLRequest requestWithURL:url];
        [self.webView.mainFrame loadRequest:req];
    }
    
    
    - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
        [self.statusLabel setStringValue:@"Loading..."];
        [self.progress startAnimation:self];
    }
    
    
    - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {
        [self.urlField setStringValue:sender.mainFrameURL];
        [self updateBackAndForwardButtons];
    }
    
    
    - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
        [self.statusLabel setStringValue:@""];
        [self.progress stopAnimation:self];
    }
    
    
    - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
        self.webView.window.title = title;
    }
    
    
    - (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
        [self.statusLabel setStringValue:@"Failed."];
        [self.progress stopAnimation:self];
        [self presentError:error];
    }
    
    
    - (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame {
        [self.statusLabel setStringValue:@"Failed."];
        [self.progress stopAnimation:self];
        [self presentError:error];
    }
    
    
    - (void)presentError:(NSError*)error {
        NSAlert *alert = [NSAlert alertWithError:error];
        [alert runModal];
    }
    
    
    - (BOOL)checkConnection {
        NSURL *url = [NSURL URLWithString:@"http://google.com/"];
        const NSTimeInterval timeout = 15;
        NSURLRequest *request =
            [NSURLRequest requestWithURL:url
    	    cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                timeoutInterval:timeout];
        NSURLResponse *response;
        NSError *error;
        NSData *data =
    	[NSURLConnection sendSynchronousRequest:request
                 returningResponse:&response
                 error:&error];
        if (data) {
            return YES;
        } else {
            [self presentError:error];
            return NO;
        }
    }
    
     
  5. Noisemaker thread starter Guest

    Joined:
    Mar 13, 2009
    #5
    Jiminaus, that was a HUGE help! that code gave me the stepping stone to fix the issue and get error alerts working flawlessly.

    Thank you so much, and have a Happy New Year!
     

Share This Page