webView:shouldStartLoadWithRequest has delay before working - ios

I would like to know why webView:shouldStartLoadWithRequest does not fire for about ~10 seconds when my app starts.
In my iOS using Cordova, I have a loading screen class that displays the loading view on app boot. The view intercepts the url load like this:
- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL* url = request.URL;
// do something
return TRUE;
}
But it takes time before the view begins to intercept the URL. I have confirmed this by placing a debugger in the method. It did not have this behavior before, and I haven't changed the loading screen class at all recently.
Any ideas? How might I resolve this?

The problem is that I did not set the delegate until later. UIWebViewDelegate needs delegate to work.
I my case, I had to do the following at the right time:
// ...
myLoadingView.delegate = self;
// ...

Related

UIWebView not working first time in iOS 9

I have a UIWebView, whose delegate is set in viewDidLoad and then a URL is passed to it. This screen is loaded once the app launches. The webviewdoesn't load the URL and the delegate method (given below) is not called
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
There is a button on the same screen. When i press that after app launches. The same Web view loads.
Please tell me why my UIWebview is not loading for the first time?
It happens only in iOS 9. In iOS 8, it works perfectly.
Add below key in you .plist and try.

Why is UIWebView canGoBack=NO in iOS7?

I'm embedding this web site into my app like this:
NSString *url = [NSString stringWithFormat:#"https://mobile.twitter.com/search?q=%#", #"#test OR #test"];
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[self.twitterWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
self.twitterWebView.scalesPageToFit = YES;
And I have 2 buttons for going back and forward in this web site. I'm calling
[self.twitterWebView goBack]; and
[self.twitterWebView goForward]; accordingly.
This works fine on iOS 6 but on iOS 7, my web view's canGoBack and canGoForward properties are NO and thus my back and forward buttons do not work.
As a side note, when the app is installed the first time, and the page is loaded the first time, my buttons work. But when I run my app again, and when I tap on a link on the web site, my web view's canGoBack property begins returning always NO.
How can I solve this?
EDIT: I uploaded a mini test app that demonstrates my problem. You can download it from here. Please run the app on an iOS 7 simulator, see that the back button is working on the first installation of the app. Then quit, run the app again and you'll see that it'll stop working.
By the way the problem seems to be about the twitter mobile site. You can try another web site address and see that.
This seems to be related to HTML5's "Application Cache" functionality. On first launch, the site isn't cached and the UIWebView correctly detects if it can go forward or back. As soon as the cache is populated, new UIWebView instances decide that, even if the URL changes (which can be observed in UIWebViewDelegate's webView:shouldStartLoadWithRequest:navigationType:), going forward or back is not possible anymore. canGoForward and canGoBack will return NO and goForward and goBack won't do anything. This persists across restarts of the app, as long as the HTML5 cache for this specific site exists.
Maybe this problem is limited to web apps that modify the URL's Fragment identifier after the hashmark via JavaScript.
And yes, the UIWebView's behavior in this situation DID change between iOS 6 and iOS 7.
I haven't found a solution yet, and we'll probably have to wait for Apple to fix this in iOS 7.1 or so.
Edit
Other people have this problem, too:
If you are using Application Cache and also managing
states through hash or other technique, the history object will not
keep your navigation history, therefore history.back() will never work
and history.length stays in 1 forever.
(from http://www.mobilexweb.com/blog/safari-ios7-html5-problems-apis-review)
Edit 2
This problem exists in Safari 7.0 (9537.71, default in OS X 10.9 Mavericks), too. However, the most recent WebKit nightly build (r158339) seems to work correctly. It's most likely only a matter of time until the fix makes it to an iOS and OS X release.
Edit 3
This problem still exists in iOS 7.1 and and OS X 10.9.2.
Edit 4
This bug has been fixed in iOS 8 and Safari 7.1 (9537.85.10.17.1) for OS X!
Related:
history object doesn't keep navigation history ios7 safari
I had this issue too in iOS 7. What worked for me was moving the "canGoBack" code and "canGoForward" code to shouldStartLoadWithRequest as shown below. Before, I had it in webViewDidFinishLoad, which worked for iOS 6, but did not for iOS 7.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([webView canGoBack])
{
[browserBackItem setEnabled:YES];
}
else
{
[browserBackItem setEnabled:NO];
}
if ([webView canGoForward])
{
[browserForwardItem setEnabled:YES];
}
else
{
[browserForwardItem setEnabled:NO];
}
return YES;
}
I had the same issue. I am able to resolve it with the following changes.
Implemented a new method updateButtons
- (void)updateButtons:(UIWebView*)theWebView {
if ([theWebView canGoBack])
{
self.backButton.enabled = YES;
}
else
{
self.backButton.enabled = NO;
}
if ([theWebView canGoForward])
{
self.forwardButton.enabled = YES;
}
else
{
self.forwardButton.enabled = NO;
}
}
Added Calling the above method in shouldStartLoadWithRequest, webViewDidFinishLoad, didFailLoadWithError events.
Now the tricky part comes. After making above changes, back and forward buttons are working as expected except in one scenario. When we are back to first page by hitting back button, it is not getting disabled. Because it will not fire any of the above events when the page is getting loaded by hitting back/forward button. it just loads from cache.
I have tried many approaches but only one that solved my problem.
Added an observer on WebHistoryItemChangedNotification.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(webViewHistoryDidChange:)
name:#"WebHistoryItemChangedNotification"
object:nil];
Called the same updatebuttons method in webViewHistoryDidChange.
- (void)webViewHistoryDidChange
{
[self updateButtons:self.webView];
}
After changing the property to "strong" reference, my problem disappeared.
before:
#property (nonatomic, weak) IBOutlet UIWebView *webView;
after changing the property to "strong":
#property (nonatomic, strong) IBOutlet UIWebView *webView;

`didFailLoadWithError:` Issues

I noticed a weird bug in my web view. I have an app that checks to see if the device is connected to the internet, if it is connected then the error image remains hidden. If it is not connected, I unhide the error image. The thing is, if I try and click on another link before the page is finished loading, didFailLoadWithError: fires and unhides the connection issue image. Here is the code I'm using:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSLog(#"didFinish: %#; stillLoading:%#", [[webView request]URL],
(webView.loading?#"NO":#"YES"));
}
-(void)webView:(UIWebView *)myWebView didFailLoadWithError:(NSError *)error {
NSLog(#"No internet connection");
_connectionError.hidden = NO;
}
If I wait until I see "still loading" in the log, then press another link, all is well. If I press a link before I see that message, then didFailLoadWithError:fires and unhides the connection issue. I'm extremely new to Objective-C, and programming in general, so I have no idea how to fix this.
Is there any simple that I can have didFailLoadWithError: only run once when the app starts up?
The didFailLoadWithError is called everytime the web view failed to load, which happens when you try to load another page before the current page is finished loading.
You should try other methods to detect if there is no internet connection, such as using Reachability: http://developer.apple.com/library/ios/#samplecode/Reachability/Introduction/Intro.html
Another way is simply calling stopLoading in webView:shouldStartLoadWithRequest:navigationType: delegate method for your particular case of triggering didFailLoadWithError when user taps on another link while the previous link is still loading in the web view.
The solution that I used was to check for the error code. If the code equaled the connection error, then I unhid the error image.

iOS UIWebView webViewDidFinishLoad is not called sometimes

Everything works fine, but sometimes uiwebview did not finish the load. I guess that sometimes uiwebview waits to long for response and than do not finish load. Had someone have familiar issue?
Yes, I have implemented the next methods:
- (void)webViewDidStartLoad:(UIWebView *)webView
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
- (void)webViewDidFinishLoad:(UIWebView *)webView
Yes, I setup the delegate. As I said - everything works fine, but sometimes it do not finish to load, it do not receives any error.
- (void)myTimer:(NSTimer *)timer
{
NSLog(#"WV=%# delegate=%# isLoading=%d", self.webView, self.webView.delegate, self.webView.isLoading);
}
It prints all the time:
[378:c07] WV=UIWebView: 0x755f690; frame = (0 0; 320 416); autoresize
= W+H; layer = CALayer: 0x755f6f0>> delegate=MainViewController: 0x755b130> isLoading=1;
I also tried to setup cache policy and disable it. It didn't help.
Can it be the problem with html frame? When it is loading some elements from the webpage are disappear (it happens when webpage is loaded, but usually after elements disappeared it shows a new page, but in this case it is not).
Did you implement didFailLoadWithError:? Implement all the delegate methods, and log various ones, and see what happens - if it just stalls or something happens before it appears to stall.
EDIT: So use a schedule NSTimer that fires every few seconds, and log the following:
the webview object
the delegate
the webView loading property
Here ist the code:
- (void)myTimer:(NSTimer *)timer
{
NSLog(#"WV=%# delegate=%# isLoading=%d", self.webView, self.webView.delegate, self.webView.isLoading);
}
Let it run for at least 10 minutes (go out and get coffee), then report back here. If it prints out all the info for a long time (like 10 min), then if you can post the URL here that would be a big help, so others can try to duplicate the problem.

UIWebView getting stuck after webViewDidStartLoad

Our iOS app has a Web View that is rendering pages from file: URLs. When the user touches an <A> element to switch pages, about 20% of the time, it gets stuck as follows:
User taps <A> link
We get WebView.shouldStartLoadWithRequest callback
We get WebView.webViewDidStartLoad callback
nothing happens after this
The screen still shows the original page with the link on it. We can break the logjam in two ways:
Rotate the device
Tap the screen
At that point, the page will immediately finish loading.
We used the recipe from here:
Javascript console.log() in an iOS UIWebView
to allow us some insight into the page load. We put the javascript-side stuff right in the first script file we load on the page, and it doesn't print its message until after we do the rotate-or-tap workaround.
So it appears that it is getting stuck somewhere between starting to load the page, and starting to evaluate the stuff on the page.
We have tried a number of work-around, none of which helped:
Setting location.href instead of using the tag
Setting location.href from javascript timeout
In the didStartLoad callback, created a thread that called setNeedDisplay on the webView over and over
Any idea what we might be doing wrong?
You could use gdb within XCode to debug the problem. I think canidates for messages that could have break points are:
- (void)webViewDidStartLoad:(UIWebView *)webView
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
I'd also add a break in whatever UIViewController is showing your UIWebView for:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
Then you could step through and hopefully catch what's wrong with your UIWebView subclass.
If you don't want to add breakpoints you could just run your app in the XCode debugger and hit the "pause execution" button above the console window when your app becomes unresponsive while loading.
It's hard to know what's going on without any code to go off of but I bet Xcode can help you find the issue quickly.
Good luck!
Found the solution for this weird behavior, at least in my case.
In my App i've created a subclass of UIWebView. I know that Apples documentation notes that you should not subclass UIWebView. But it's "necessary" in my App.
The problem was, that i've overwritten scrollViewDidEndDragging:willDecelerate: without calling super.
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// my code
}
becomes to
- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
[super scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
// my code
}
Now it always loads the web site when tapping on a html link.

Resources