Why is UIWebView canGoBack=NO in iOS7?

。_饼干妹妹 提交于 2019-11-27 20:42:33
Andreas Ley

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:

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];
}
YongJiang Zhang

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;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!