WebView中的本地存储不是持久化的。

6
我正在尝试在Cocoa的WebView中使本地存储工作。我使用了另一个SO问题中显示的代码,但对我来说它无法正常工作。本地存储被正确创建并在重新加载时保留其内容,但每当应用程序重新启动时,旧的本地存储就会立即被删除。
例如,我创建了一个新项目,并在窗口内设置了一个WebView。然后我将以下代码放入我的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"];
}

本地存储已正确存储在正确的文件夹中,并且即使退出应用程序后仍然保留在那里,但是当再次启动应用程序时,旧的本地存储将被删除并创建一个新文件。

你最终解决了这个问题吗?我也遇到了同样的问题! - NycCompSci
据我所知,本地存储已不再是HTML5规范的一部分。 - Christian Kienle
1
由于下划线表示,"_setLocalStorageDatabasePath:"是私有API... - Vincent Gable
2个回答

9

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

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

点击下载WebStorageManagerPrivate.h

在其中添加以下几行:

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

这些代码可以让你获取WebKit本地存储跟踪器数据库的目录位置。这很重要,因为由于WebKit中的一个错误,在不将LocalStorage WebView文件存储在跟踪器数据库相同的目录中的情况下,它们会在你运行应用程序的每隔一次就被删除。我没有在WebStorageManager代码中找到更改单个应用程序位置的方法。它总是从用户首选项中读取。

在你的appDelegate中包含WebStorageManagerPrivate.h文件。

#include "WebStorageManagerPrivate.h"

您需要下载并包含另一个头文件,该文件未包含在XCode分发中。请将其保存为WebPreferencesPrivate.h。 点击此处下载WebPreferencesPrivate.h 将WebPreferencesPrivate.h包含在您的appDelegate中即可。
#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彻底修复这个问题。

我假设如果你想在iOS中实现这个功能,尽管它“可能”有效,但当你将应用程序提交到App Store时,苹果绝对不会接受它,因为他们严格禁止使用私有API。 - Roberto Andrade

5

目前,OS X 上的 WebView 不支持使用 localStorage。如果您想请求此功能,最好的方法是在 https://developer.apple.com/bugreporter/ 上提交一个错误报告,并提到它是 #11026838 的重复。

您需要使用 Cocoa API 来存储数据,以便在应用程序启动时保留数据。

对于简单的“首选项”数据,NSUserDefaults 是最好的解决方案。它是一个简单的键/值存储,类似于 localStorage 提供的功能。

对于更复杂的数据,您可能需要考虑使用 NSKeyedArchiverNSKeyedUnarchiver,请参阅 档案和序列化编程指南

对于极其复杂或高性能的数据,您可以使用 Core Data

如需了解有关 Objective-C 和 JavaScript 之间互操作的更多信息,请参阅 从 JavaScript 调用 Objective-C 方法


1
从Javascript调用Objective-C方法的实际链接:http://developer.apple.com/library/safari/#documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/ObjCFromJavaScript.html - hendrikswan
经过进一步的研究,我发现上面链接中指定的“从JavaScript调用Objective-C方法”仅在macOS上受支持。相反,请查看此stackoverflow帖子 - hendrikswan

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