NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:self.webView forKey:@"webView"];
The code above is made to save a WKWebView object but I'm getting a compiler error:
2014-11-08 14:58:52.561 Restoration[2431:482391] Property list invalid
for format: 200 (property lists cannot contain objects of type
'CFType') 2014-11-08 14:58:52.564 Restoration[2431:482391] Attempt to
set a non-property-list object > as an
NSUserDefaults/CFPreferences value for key webView 2014-11-08
14:58:52.566 Restoration[2431:482391] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to
insert non-property list object > for key webView'
* First throw call stack: (0x2c491c1f 0x39c78c8b 0x2c491b65 0x2c4cbe51 0x2c436599 0x2c4358d7 0x2c4cc0d1 0x2c4cb769 0x2c4ce95b
0x2c4ce875 0x2d0eab69 0x66bdf 0x2f981c2b 0x2f981bd1 0x2f96c863
0x2f98163d 0x2f981317 0x2f97abe1 0x2f9513dd 0x2fbc4c29 0x2f94fe39
0x2c458377 0x2c457787 0x2c455ded 0x2c3a4211 0x2c3a4023 0x3379d0a9
0x2f9b01d1 0x66ead 0x3a1f8aaf) libc++abi.dylib: terminating with
uncaught exception of type NSException
How can I save the WKWebView and restore it with its history intact?
EDIT:
8 months have passed and there's no solution to this problem...
EDIT 2:
I'm making a web browser and it is crucial when the user restarts the app the web views (tabs) to restore so he can press the back button and go back.
If I save the previous URLs in a simple list I can't put them back into the web view when the app restarts. I can only load the first page. So, the user can't press back because there is no page to back. If it was as simple as saving a list of URLs I wouldn't start a bounty. Since, a web browser is a very complex app I've been very close to the fundamentals of the webViews and I have even submitted 3 bugs from which only 2 have been resolved. Including the infamous screenshot bug.
The standardUserDefaults method does work with UIWebView but Apple states that all developers should use the WKWebView following the release of iOS 7. I'm expecting UIWebView to be deprecated in the near future.
There is no easy answer here. The WKWebView cannot be archived and it does also not participate in UI state preservation/restoration. You already discovered this.
For Firefox for iOS we took a different route to work around these limitations. This far from ideal but it does work.
When we restore a tab that has session info (previously visited pages) attached, we load a special html page from a local web server (running on localhost) that modifies the push state of the page and pushes previously visited URLs on the history stack.
Because these URLs need to be of same origin, we basically push urls like `http://localhost:1234/history/item?url=http://original.url.com
In our UI we translate this to display original.url.com
. When the user goes back in history to load these, we intercept and instead of loading the page from localhost, we load the original page.
It is a big hack but that is all we have at this point.
See the source code at https://github.com/mozilla/firefox-ios
you can only store certain types of objects in NSUserDefaults, namely
NSArray
NSData
NSDate
NSDictionary
NSNumber
NSString
(you cant bypass this by putting your webview inside an NSArray)
what you could do is store relevant information about the webview in an NSDictionary that would allow you to be able to get your webview back into its current state when loading from the NSUserDefaults
you can refer to the documentation for more details
As @fonix mentioned, you can only store a select few data types in NSUserDefault
.
If you just wanted the url, it would be pretty easy to convert that to a string and save it to NSUserDefaults
.
However, the crux of the question is how to "restore the WKWebview
with its history intact."
Since, to 'save' the web view, you want not only the current URL being shown, but also the history, you need access the backForwardList
on WKWebview.
NSMutableArray *history = [NSMutableArray array];
for(WKBackForwardListItem *item in webview.backForwardList.backList){
// use -absoluteString to convert NSURL to NSString
[history addObject:[item.url absoluteString]];
}
[[NSUserDefaults standardUserDefaults] addObject:history forKey:@"webviewHistory"];
[[NSUserDefaults standardUserDefaults] synchronize];
Saving those URLS into an NSArray
, will allow you to save them to NSUserDefaults
.
Then when you want to 'recreate' the webview, iterate through this array and request each url to simulate the history.
Hope this helps!
In case you really want the webview from user default, here is a choice.
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:[NSKeyedArchiver archivedDataWithRootObject:self.webView] forKey:@"webView"];
// get it back from user default
NSData *data = [prefs objectForKey:@"webView"];
self.webView = [NSKeyedUnarchiver unarchiveObjectWithData:data];