Restore Position in UIWebView

1.6k views Asked by At

I need to store the current position in a UIWebView to disk and reload it from disk on a later launch.

What I did before was to store the window.scrollX and window.scrollY with an javascript position. This works good for many cases.

Additionally I store the scale by getting the current:

webView.scrollView.zoomScale

and restore it by setting the viewports initial scale to it with javascript.

All of this works but isn't reliable. Is there an better way?

I read about UIWebView's restorationIdentifier but I'm not sure if I can save it to disk?

2

There are 2 answers

4
gabbler On BEST ANSWER

In iOS 6 and later, if you assign a value to this view’s restorationIdentifier property, it attempts to preserve its URL history, the scaling and scrolling positions for each page, and information about which page is currently being viewed. During restoration, the view restores these values so that the web content appears just as it did before.

See more from Apple Programming Guide and a tutorial along with a sample project. You can run it and send the app to the background, then stop running it with Xcode, next time you open the app, it will restore its state to the state before app entering to the background. There can be a small fix on the sample project, in viewDidAppear, if self.restoringState is NO, you call showPage function.

0
surui On

Just to be clear, the steps for UIWebView state restoration (similar to the normal state restoration) are as follows:

  1. In your app delegate application: shouldRestoreApplicationState, application: shouldSaveApplicationState return true.
  2. Presented view controller- set its Restoration ID - you can do it in the storyboard's identity inspector. The ID can be any unique string. If you have a container VC (navigation, etc) you need to set a restoration ID for it.
  3. Set the Restoration ID for the UIWebView in your storyboard
  4. Override applicationFinishedRestoringState and reload the webView

I used these step, and everything seemed to work. However, after reading your comments I saw you were having problems with zoomed pages. The problem is a bug in UIWebView restoration (I think) and it has to do with the reloading mechanism. That's why I suggest the following hack:

import UIKit

class ViewController: UIViewController, UIWebViewDelegate {

    @IBOutlet var webView: UIWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        webView.delegate = self
        webView.scrollView.restorationIdentifier = "webViewScrollView"
    }

    var restoring = false
    override func viewDidAppear(animated: Bool) {
        if !restoring {
            webView.loadRequest(NSURLRequest(URL: NSURL(string: "http://google.com")!))
        }

    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    var restoredScrollOffset: CGPoint = CGPoint.zeroPoint
    override func applicationFinishedRestoringState() {
        restoring = true
        restoredScrollOffset = webView.scrollView.contentOffset
        webView.reload()
    }

    func webViewDidFinishLoad(webView: UIWebView) {
        if restoring {
            restoring = false
            if webView.scrollView.contentOffset != restoredScrollOffset {
                println("bug - sometimes it may happen")
            }
            webView.scrollView.contentOffset = restoredScrollOffset
        }
   }

because it's a hack we can't be sure it will be flawless :)

Note that I set the restoration identifier of the scroll view within the webview, just so I wouldn't have to implement the VC encode function - it's possible to encode only the scrollview offset via the VC encode/decode overrides.

I only set the scroll view offset; if you have problems with the zoom scale (which I didn't find in any web page I tried) you can just set the scale in the same place I set the content offset of the scroll view

The code is in https://github.com/iamdoron/UIWebViewRestoration