如何在基于WebKit的应用程序中启用本地存储?

12
我有一个嵌入了WebKit WebView的Cocoa/Objective-C应用程序。我需要打开数据库支持和本地存储。我知道可以做到这一点-我在Safari中使用它-但我找不到如何在自己的应用程序中设置这个的示例。
我找到这个(未解答)SO问题,其中提供了一个示例,但正如原始发布者所提到的,它不起作用。事实上,他使用的方法(setDatabasesEnabled,setLocalStorageEnabled)在我的WebKit.framework(Xcode 3.2.5)中没有定义,尽管如果我自己定义它们,它们似乎存在。
是否有人可以提供一个示例,说明如何为基于WebKit的Cocoa应用程序启用本地数据库存储?如果是这样,非常感谢!
更新:我已经有了一些工作......我对“数据库”与“本地存储”感到困惑,这显然是两种完全不同的东西。这是有效的代码:
WebPreferences* prefs = [webView preferences];
[prefs _setLocalStorageDatabasePath:@"~/Library/Application Support/MyApp"];
[prefs setLocalStorageEnabled:YES];

这样可以实现,但需要使用私有方法_setLocalStorageDatabasePath,这意味着我不能在应用商店中使用。因此,我的修改后的问题是:是否有一种方法可以在不使用私有方法的情况下使其工作?我在这个答案中找到了WebDatabaseDirectory preference key,它控制着数据库的位置。但我在源代码中找不到相应的本地存储键。或者有没有办法强制本地存储使用数据库,从而使用WebDatabaseDirectory键?有什么想法吗?

3个回答

11

我使用以下代码在Mac应用商店提交了一个应用,并且被苹果公司批准:

Objective-C

WebPreferences* prefs = [webView preferences];
[prefs _setLocalStorageDatabasePath:@"~/Library/Application Support/MyApp"];
[prefs setLocalStorageEnabled:YES];

Swift 3

var prefs: WebPreferences? = webView.preferences
prefs?._setLocalStorageDatabasePath("~/Library/Application Support/MyApp")
prefs?.localStorageEnabled = true

我不知道他们是否会继续批准,但截至2011-01-29,他们允许了我的应用程序。 更新: 他们还批准了同一应用程序的版本更新,因此已经通过两次。


终于成功地通过了最后一组障碍,我的应用程序现在也已经上架了。 - J. Perkins
4
您要把它放在哪里?是在 @implementation 中还是 .h 文件中?希望能得到澄清。非常抱歉,我可能比较蠢,需要您耐心解答。 - Alex Gray
通常情况下,苹果会批准大多数 WebKit 私有方法,因为 WebKit 本身是开源的。 - Rob Keniger
2
这个问题最后一次活跃是大约一年前,所以苹果可能已经移除了对 _setLocalStorageDatabasePath:setLocalStorageEnabled: 方法的支持,因为我无法在任何地方找到使用它们的方法,但如果您知道仍然有支持,那么我该如何将这些方法的支持添加到我的代码中,以便我可以使用它们? - Carter Pape
你怎么用Swift实现? - Juanjo Conti

4
我将采用Javascript到Objective-C桥接的方法,并将所有内容存储在核心数据中。将localStorage设为false,然后构建一个JS对象和一个同名的实例"localStorage"具有相同的方法。我的JavaScript开发人员不会察觉到区别,并且我已经不得不在Air中做了同样的事情(基本上是这样)。尽管它实际上并没有将它们存储在持久数据库中,但还有另一种方法可以保留localStorage的完整性。可以通过javascript迭代元素并从那里进行操作,但我认为最好是用自己的对象来替换它。

1
听起来像是一个有趣的解决方案(不会被苹果标记)。我真的很想看到一些代码 :) - richtaur
这种方法唯一的问题是,如果使用sqlite,则查询会异步运行,因此alert(localStorage.getItem('a'));将无法工作。 - Brian Antonelli
1
我在哪里可以找到这种方法的示例? - michael_erasmus
1
很棒的是,开源这个桥梁将会是非常好的。 - philfreo
你是如何替换window.localStorage为自己的实现的?我成功地实现了一个LocalStorage对象,但是我无法将其分配给window.localStorage。 - Arnaud Le Blanc
例如,您可以覆盖Storage.prototype.setItem = function(key, value) { ...}。所有方法都可以被覆盖。 - Derek Wade

3

经过大量的痛苦和挫折,我找到了一种方法来启用本地存储,并使其在应用程序运行期间持久化。此解决方案专门针对OSX,但它也可能适用于iOS。

下载并将此头文件添加到您的项目中。它未包含在XCode Webkit分发中。

点击下载WebStorageManagerPrivate.h

在其中加入以下几行:

static NSString* _storageDirectoryPath();
+ (NSString *)_storageDirectoryPath;

使用这些方法可以获取WebKit本地存储跟踪器数据库的目录位置。由于WebKit中存在一个bug,如果您没有将LocalStorage WebView文件存储在与跟踪器数据库相同的目录中,则每隔一段时间应用程序会将其删除。我没有在WebStorageManager代码中找到更改单个应用程序位置的方式。它始终从用户首选项中读取。
在您的appDelegate中包含WebStorageManagerPrivate.h。
#include "WebStorageManagerPrivate.h"

您需要下载并在项目中包含另一个头文件,该文件未包含在XCode发行版中。请将其保存为WebPreferencesPrivate.h。 点击下载WebPreferencesPrivate.h 在您的appDelegate中包含WebPreferencesPrivate.h即可。
#include "WebPreferencesPrivate.h"

现在,在您的applicationDidFinishLaunching处理程序中使用以下代码来初始化和启用LocalStorage。该代码假定您有一个名为“webView”的IBOutlet,用于您正在使用的WebView。

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

我希望这可以帮助那些曾经或仍在遭受此问题困扰的人,直到在WebKit中得到适当修复。

你遇到了什么问题?出现了错误吗?无法保存?我已经在10.7下测试过了,没有问题。 - Derek Wade
在10.11(El Capitan)以下版本,这不再起作用。我不得不采用桥接到本地代码进行保存和加载操作。为了最小化更改Javascript,您可以覆盖Storage.prototype中的标准“set”和“get”函数,并调用您的桥接函数。苹果公司收紧了对使用本地文件引用存储localStorage的Webkit应用程序的安全处理。 - Derek Wade

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接