I have a simple iOS native app that loads a single UIWebView. I would like the webView to show an error message if the app doesn't COMPLETELY finish loading the initial page in the webView within 20 seconds.
I load my URL for the webView within my viewDidLoad
like this (simplified):
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.example.com"] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:20.0]];
The timeoutInterval
within the code above does not actually "do" anything, as Apple has it set within the OS to not actually time out for 240 seconds.
I have my webView didFailLoadWithError
actions set, but if the user HAS a network connection, this never gets called. The webView just continues to try loading with my networkActivityIndicator spinning.
Is there a way to set a timeout for the webView?
The timeoutInterval is for connection. Once webview connected to the URL, you'll need to start NSTimer and do your own timeout handling. Something like:
// define NSTimer *timer; somewhere in your class
- (void)cancelWeb
{
NSLog(@"didn't finish loading within 20 sec");
// do anything error
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[timer invalidate];
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
// webView connected
timer = [NSTimer scheduledTimerWithTimeInterval:20.0 target:self selector:@selector(cancelWeb) userInfo:nil repeats:NO];
}
All of the suggested solutions are not ideal. The correct way to handle this is using the timeoutInterval on the NSMutableURLRequest
itself:
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://web.site"]];
request.timeoutInterval = 10;
[webview loadRequest:request];
My way is similar to accepted answer but just stopLoading when time out and control in didFailLoadWithError.
- (void)timeout{
if ([self.webView isLoading]) {
[self.webView stopLoading];//fire in didFailLoadWithError
}
}
- (void)webViewDidStartLoad:(UIWebView *)webView{
self.timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(timeout) userInfo:nil repeats:NO];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[self.timer invalidate];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error{
//Error 999 fire when stopLoading
[self.timer invalidate];//invalidate for other errors, not time out.
}
Swift coders can do it as follow:
var timeOut: NSTimer!
func webViewDidStartLoad(webView: UIWebView) {
self.timeOut = Timer.scheduledTimer(timeInterval: 7.0, target: self, selector: Selector(("cancelWeb")), userInfo: nil, repeats: false)
}
func webViewDidFinishLoad(webView: UIWebView) {
self.timeOut.invalidate()
}
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
self.timeOut.invalidate()
}
func cancelWeb() {
print("cancelWeb")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With