Reputation: 61
I'm trying to get local storage to work in a WebView in Cocoa. I used code shown here in another SO question, but it doesn't work properly for me. The local storage is created properly and keeps its contents across reloads, but whenever the application is restarted, the old local storage is immediately deleted.
For example, I created a new project and set up a WebView inside the window. I then put the following code in my AppDelegate.m
:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
WebPreferences *prefs = [webView preferences];
[prefs _setLocalStorageDatabasePath:@"~/Library/Application Support/Test"];
[prefs setLocalStorageEnabled:YES];
[webView setMainFrameURL:@"http://static.diveintojavascript.com/files/tutorials/web-storage-contacts/contacts.html"];
}
The local storage is stored properly in the correct folder and stays there even after quitting the app, but when the app is started again the old local storage is deleted and a new file is created.
Upvotes: 6
Views: 4212
Reputation: 746
After a lot of pain and frustration I found a way to enable local storage and have it persist across application runs properly. This solution is specifically for OSX, but it may be applicable to iOS as well.
Download and add this header file into your project. It's not included in the XCode Webkit distribution.
click to download WebStorageManagerPrivate.h
Add to it, the following lines:
static NSString* _storageDirectoryPath();
+ (NSString *)_storageDirectoryPath;
These allow you to retrieve the directory location of the WebKit local storage tracker database. This is important because due to a bug in WebKit, if you don't store your LocalStorage WebView files in the same directory as the tracker database, they are deleted every other time you run your application. I didn't see a way in the WebStorageManager code to change this location for an individual application. It is always read from the user preferences.
Include the WebStorageManagerPrivate.h in your appDelegate.
#include "WebStorageManagerPrivate.h"
You need to download and include in your project another header not included in XCode distribution. Save it as WebPreferencesPrivate.h
click to download WebPreferencesPrivate.h
Include the WebPreferencesPrivate.h in your appDelegate.
#include "WebPreferencesPrivate.h"
Now use the code below in your applicationDidFinishLaunching handler to initialize and enable LocalStorage. The code assumes you have an IBOutlet named 'webView' for the WebView you are using.
NSString* dbPath = [WebStorageManager _storageDirectoryPath];
WebPreferences* prefs = [self.webView preferences];
NSString* localDBPath = [prefs _localStorageDatabasePath];
// PATHS MUST MATCH!!!! otherwise localstorage file is erased when starting program
if( [localDBPath isEqualToString:dbPath] == NO) {
[prefs setAutosaves:YES]; //SET PREFS AUTOSAVE FIRST otherwise settings aren't saved.
// Define application cache quota
static const unsigned long long defaultTotalQuota = 10 * 1024 * 1024; // 10MB
static const unsigned long long defaultOriginQuota = 5 * 1024 * 1024; // 5MB
[prefs setApplicationCacheTotalQuota:defaultTotalQuota];
[prefs setApplicationCacheDefaultOriginQuota:defaultOriginQuota];
[prefs setWebGLEnabled:YES];
[prefs setOfflineWebApplicationCacheEnabled:YES];
[prefs setDatabasesEnabled:YES];
[prefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]];
#ifdef DEBUG
[prefs setDeveloperExtrasEnabled:YES];
#endif
[prefs _setLocalStorageDatabasePath:dbPath];
[prefs setLocalStorageEnabled:YES];
[self.webView setPreferences:prefs];
}
I hope this helps others have struggled or are still struggling with this issue, until it is fixed properly within WebKit.
Upvotes: 9
Reputation: 3465
WebView
on OS X does not support localStorage
at this time. The best way to ask for this feature is to file a bug at https://developer.apple.com/bugreporter/ and mention that it is a duplicate of #11026838.
You will have to store your data using Cocoa APIs to persist it across application launches.
For simple "preference" like data, NSUserDefaults is the best solution. It is a simple key/value store, similar to what localStorage offers.
For more complex data, you may want to look at using NSKeyedArchiver
and NSKeyedUnarchiver
, see the Archives and Serializations Programming Guide.
For extremely complex or high-performance data, you could use Core Data.
For more information on interoperating Objective-C and JavaScript, see Calling Objective-C Methods From JavaScript.
Upvotes: 5