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

时间:2021-12-23 07:30:16

I have a Cocoa/Objective-C application which embeds a WebKit WebView. I need to turn on database support and local storage. I know it can be done--I have it working in Safari--but I can't find an example of how to set this up in my own application.

我有一个嵌入WebKit WebView的Cocoa / Objective-C应用程序。我需要打开数据库支持和本地存储。我知道它可以完成 - 我在Safari中工作 - 但我找不到如何在我自己的应用程序中设置它的示例。

I found this (unanswered) SO question which provides an example but, as the original poster mentions, doesn't work. And in fact, the methods he uses (setDatabasesEnabled, setLocalStorageEnabled) aren't defined in my WebKit.framework (Xcode 3.2.5), although they appear to exist if I define them myself.

我发现这个(未答复的)SO问题提供了一个例子,但正如原始海报所提到的那样,它不起作用。事实上,他使用的方法(setDatabasesEnabled,setLocalStorageEnabled)没有在我的WebKit.framework(Xcode 3.2.5)中定义,尽管如果我自己定义它们似乎存在它们。

Can anyone provide an example of how to enable local database storage for a WebKit-based Cocoa application? Many thanks if so!

任何人都可以提供一个如何为基于WebKit的Cocoa应用程序启用本地数据库存储的示例吗?非常感谢,如果有的话

Update: I've got something working...I was confused by "databases" vs. "local storage", which are apparently quite different things. Here's the code that works:

更新:我有一些工作......我对“数据库”与“本地存储”感到困惑,这显然是完全不同的东西。这是有效的代码:

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

So that works, but it requires the private method _setLocalStorageDatabasePath, which means no App Store for me. So my amended questions is now: is there a way to make this work without using a private method? I found the WebDatabaseDirectory preference key in this answer, which controls where databases go. But I couldn't find a corresponding key for local storage anywhere in the sources. Or is there a way for me to force local storage to use the database, and so the WebDatabaseDirectory key? Any ideas?

这样可行,但它需要私有方法_setLocalStorageDatabasePath,这意味着我没有App Store。所以我现在修改过的问题是:有没有办法在不使用私有方法的情况下完成这项工作?我在这个答案中找到了WebDatabaseDirectory首选项键,它控制数据库的位置。但我无法在源中的任何位置找到相应的本地存储密钥。或者有没有办法强制本地存储使用数据库,所以WebDatabaseDirectory键?有任何想法吗?

3 个解决方案

#1


11  

I submitted an app using this code to the Mac App Store, and Apple approved it:

我使用此代码将应用程序提交到Mac App Store,Apple批准了它:

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

Whether they will continue to approve that, I don't know, but they allowed it for my application as of 2011-01-29. Update: They also approved a version update to the same app, so it has gone through twice.

他们是否会继续批准,我不知道,但他们允许我在2011-01-29申请。更新:他们还批准了对同一个应用程序的版本更新,因此它经历了两次。

#2


4  

I'm going to take the Javascript to Objective-C bridge approach and store everything in core data. Set localStorage to false, then build a JS object and an instance named "localStorage" with the same methods. My javascript devs won't know the difference, and I already had to do the same thing with Air (basically). There's another way to leave the localStorage intact even though it doesn't actually store them in a persistent db. The elements can be iterated through in javascript and manipulated from there, but I think it will be better to simply replace the object with my own.

我将采用Javascript到Objective-C桥接方法并将所有内容存储在核心数据中。将localStorage设置为false,然后使用相同的方法构建JS对象和名为“localStorage”的实例。我的javascript开发人员不会知道差异,我已经不得不用Air(基本上)做同样的事情。还有另一种方法可以保持localStorage完好无损,即使它实际上并没有将它们存储在持久数据库中。元素可以在javascript中迭代并从那里进行操作,但我认为用自己的方法替换对象会更好。

#3


4  

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.

在经历了很多痛苦和挫折之后,我找到了一种启用本地存储的方法,并使其在应用程序运行中保持正常运行。此解决方案专门针对OSX,但也可能适用于iOS。

Download and add this header file into your project. It's not included in the XCode Webkit distribution.

下载此头文件并将其添加到项目中。它不包含在XCode Webkit发行版中。

click to download WebStorageManagerPrivate.h

单击下载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.

这些允许您检索WebKit本地存储跟踪器数据库的目录位置。这很重要,因为由于WebKit中的错误,如果您不将LocalStorage WebView文件存储在跟踪器数据库所在的目录中,则每次运行应用程序时都会删除它们。我没有在WebStorageManager代码中看到为单个应用程序更改此位置的方法。始终从用户首选项中读取。

Include the WebStorageManagerPrivate.h in your appDelegate.

在appDelegate中包含WebStorageManagerPrivate.h。

#include "WebStorageManagerPrivate.h"

You need to download and include in your project another header not included in XCode distribution. Save it as WebPreferencesPrivate.h

您需要下载并在项目中包含另一个未包含在XCode发行版中的标头。将其另存为WebPreferencesPrivate.h

click to download WebPreferencesPrivate.h

单击下载WebPreferencesPrivate.h

Include the WebPreferencesPrivate.h in your appDelegate.

在appDelegate中包含WebPreferencesPrivate.h。

#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.

现在使用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];
    }

I hope this helps others have struggled or are still struggling with this issue, until it is fixed properly within WebKit.

我希望这有助于其他人一直在努力或仍在努力解决这个问题,直到它在WebKit中正确修复。

#1


11  

I submitted an app using this code to the Mac App Store, and Apple approved it:

我使用此代码将应用程序提交到Mac App Store,Apple批准了它:

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

Whether they will continue to approve that, I don't know, but they allowed it for my application as of 2011-01-29. Update: They also approved a version update to the same app, so it has gone through twice.

他们是否会继续批准,我不知道,但他们允许我在2011-01-29申请。更新:他们还批准了对同一个应用程序的版本更新,因此它经历了两次。

#2


4  

I'm going to take the Javascript to Objective-C bridge approach and store everything in core data. Set localStorage to false, then build a JS object and an instance named "localStorage" with the same methods. My javascript devs won't know the difference, and I already had to do the same thing with Air (basically). There's another way to leave the localStorage intact even though it doesn't actually store them in a persistent db. The elements can be iterated through in javascript and manipulated from there, but I think it will be better to simply replace the object with my own.

我将采用Javascript到Objective-C桥接方法并将所有内容存储在核心数据中。将localStorage设置为false,然后使用相同的方法构建JS对象和名为“localStorage”的实例。我的javascript开发人员不会知道差异,我已经不得不用Air(基本上)做同样的事情。还有另一种方法可以保持localStorage完好无损,即使它实际上并没有将它们存储在持久数据库中。元素可以在javascript中迭代并从那里进行操作,但我认为用自己的方法替换对象会更好。

#3


4  

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.

在经历了很多痛苦和挫折之后,我找到了一种启用本地存储的方法,并使其在应用程序运行中保持正常运行。此解决方案专门针对OSX,但也可能适用于iOS。

Download and add this header file into your project. It's not included in the XCode Webkit distribution.

下载此头文件并将其添加到项目中。它不包含在XCode Webkit发行版中。

click to download WebStorageManagerPrivate.h

单击下载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.

这些允许您检索WebKit本地存储跟踪器数据库的目录位置。这很重要,因为由于WebKit中的错误,如果您不将LocalStorage WebView文件存储在跟踪器数据库所在的目录中,则每次运行应用程序时都会删除它们。我没有在WebStorageManager代码中看到为单个应用程序更改此位置的方法。始终从用户首选项中读取。

Include the WebStorageManagerPrivate.h in your appDelegate.

在appDelegate中包含WebStorageManagerPrivate.h。

#include "WebStorageManagerPrivate.h"

You need to download and include in your project another header not included in XCode distribution. Save it as WebPreferencesPrivate.h

您需要下载并在项目中包含另一个未包含在XCode发行版中的标头。将其另存为WebPreferencesPrivate.h

click to download WebPreferencesPrivate.h

单击下载WebPreferencesPrivate.h

Include the WebPreferencesPrivate.h in your appDelegate.

在appDelegate中包含WebPreferencesPrivate.h。

#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.

现在使用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];
    }

I hope this helps others have struggled or are still struggling with this issue, until it is fixed properly within WebKit.

我希望这有助于其他人一直在努力或仍在努力解决这个问题,直到它在WebKit中正确修复。