`

Relocating localStorage in iOS 5.1 for PhoneGap Applications(转)

 
阅读更多

See bug details here: https://issues.apache.org/jira/browse/CB-330

The general problem is that as of iOS update 5.1 (3/2012), Apple no longer considers data stored in localStorage or the SQL Lite DB to be persistent data. This means that any data stored using these HTML5 features is considered volatile across updates and process termination. To say the least, this is a problem for any developers replying on this data being available across app updates, backups, or crashes. It’s bad enough that we only get 5MB of storage (2.5MB if you’re storing 16bit text characters), now we can’t even persist the data when the app is run natively? That’s yucky.

Product groups like Sencha, Ext4.js, and  PohoneGap are working on work arounds for this new Apple specification but as of this entry, they aren’t all there yet. Until a fix exits for Sencha, I’ve taken the approach of changing the default location of localStorage and the SQL DB that resides within the app container on the device. This solution solves the problem entirely and has the added benefit of tons more storage capacity. The down side is that it requires modification of the native code-base and therefore requires apps for the iOS system to be built in xcode. Consequently, mobile app dev for iOS using this approach now requires a Mac. Lucky me, I have me some Macs.

The Fix

Copy and paste the following code into AppDelegate.m‘s method didFinishLaunchingWithOptions. The placement likely doesn’t matter but I add it as the first block of code.

You can read through the code to see that it won’t affect you older iOS devices and that it just relates where the localStorage mechanism point to on the device.

/* Fix problem with ios 5.0.1+ and Webkit databases described at the following urls:
     *   https://issues.apache.org/jira/browse/CB-347
     *   https://issues.apache.org/jira/browse/CB-330
     * My strategy is to move any existing database from default paths
     * to Documents/ and then changing app preferences accordingly
     */

    NSString* library = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)objectAtIndex:0];
    NSString* documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

    NSString *localStorageSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/LocalStorage";
    NSString *localStoragePath = [library stringByAppendingPathComponent:localStorageSubdir];
    NSString *localStorageDb = [localStoragePath stringByAppendingPathComponent:@"file__0.localstorage"];

    NSString *WebSQLSubdir = (IsAtLeastiOSVersion(@"5.1")) ? @"Caches" : @"WebKit/Databases";
    NSString *WebSQLPath = [library stringByAppendingPathComponent:WebSQLSubdir];
    NSString *WebSQLIndex = [WebSQLPath stringByAppendingPathComponent:@"Databases.db"];
    NSString *WebSQLDb = [WebSQLPath stringByAppendingPathComponent:@"file__0"];

    NSString *ourLocalStoragePath = [documents stringByAppendingPathComponent:@"LocalStorage"];;
    //NSString *ourLocalStorageDb = [documents stringByAppendingPathComponent:@"file__0.localstorage"];
    NSString *ourLocalStorageDb = [ourLocalStoragePath stringByAppendingPathComponent:@"file__0.localstorage"];

    NSString *ourWebSQLPath = [documents stringByAppendingPathComponent:@"Databases"];
    NSString *ourWebSQLIndex = [ourWebSQLPath stringByAppendingPathComponent:@"Databases.db"];
    NSString *ourWebSQLDb = [ourWebSQLPath stringByAppendingPathComponent:@"file__0"];

    NSFileManager* fileManager = [NSFileManager defaultManager];

    BOOL copy;
    NSError *err = nil; 
    copy = [fileManager fileExistsAtPath:localStorageDb] && ![fileManager fileExistsAtPath:ourLocalStorageDb];
    if (copy) {
        [fileManager createDirectoryAtPath:ourLocalStoragePath withIntermediateDirectories:YES attributes:nil error:&err];
        [fileManager copyItemAtPath:localStorageDb toPath:ourLocalStorageDb error:&err];
        if (err == nil)
            [fileManager removeItemAtPath:localStorageDb error:&err];
    }

    err = nil;
    copy = [fileManager fileExistsAtPath:WebSQLPath] && ![fileManager fileExistsAtPath:ourWebSQLPath];
    if (copy) {
        [fileManager createDirectoryAtPath:ourWebSQLPath withIntermediateDirectories:YES attributes:nil error:&err];
        [fileManager copyItemAtPath:WebSQLIndex toPath:ourWebSQLIndex error:&err];
        [fileManager copyItemAtPath:WebSQLDb toPath:ourWebSQLDb error:&err];
        if (err == nil)
            [fileManager removeItemAtPath:WebSQLPath error:&err];
    }

    NSUserDefaults* appPreferences = [NSUserDefaults standardUserDefaults];
    NSBundle* mainBundle = [NSBundle mainBundle];

    NSString *bundlePath = [[mainBundle bundlePath] stringByDeletingLastPathComponent];
    NSString *bundleIdentifier = [[mainBundle infoDictionary] objectForKey:@"CFBundleIdentifier"];
    NSString* libraryPreferences = @"Library/Preferences";

    NSString* appPlistPath = [[bundlePath stringByAppendingPathComponent:libraryPreferences]    stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", bundleIdentifier]];
    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithContentsOfFile:appPlistPath];

    BOOL dirty = NO;

    NSString *value;
    NSString *key = @"WebKitLocalStorageDatabasePathPreferenceKey";
    value = [appPlistDict objectForKey: key];
    if (![value isEqual:ourLocalStoragePath]) {
        [appPlistDict setValue:ourLocalStoragePath forKey:key];
        dirty = YES;
    }

    key = @"WebDatabaseDirectory";
    value = [appPlistDict objectForKey: key];
    if (![value isEqual:ourWebSQLPath]) {
        [appPlistDict setValue:ourWebSQLPath forKey:key];
        dirty = YES;
    }

    if (dirty) 
    {
        BOOL ok = [appPlistDict writeToFile:appPlistPath atomically:YES];
        NSLog(@"Fix applied for database locations?: %@", ok? @"YES":@"NO");
        [appPreferences synchronize];
    }
    /* END Fix problem with ios 5.0.1+ and Webkit databases */

 

Next, copy and paste the following code in AppDelegate.h. Place it as the last line of code above @end

/* 
 * Returns YES if it is at least version specified as NSString(X)
 */
#define IsAtLeastiOSVersion(X) ([[[UIDevice currentDevice] systemVersion] compare:X options:NSNumericSearch] != NSOrderedAscending)

 

分享到:
评论

相关推荐

    s32k312 之 Relocating code in ITCM

    ### S32K312 之 Relocating code in ITCM #### 概述 在嵌入式系统设计中,为了优化程序性能及内存使用效率,开发人员经常需要利用特殊的内存区域来存放关键代码或者数据。其中,ITCM(Instruction Tight-Coupled ...

    s32k312 之 Relocating data in DTCM

    ### S32K312 之 Relocating data in DTCM #### 知识点一:理解DTCM(数据紧耦合内存) **DTCM**(Data Tight Coupled Memory)是一种特殊的内存区域,它与处理器紧密耦合,提供高速的数据访问能力。在嵌入式系统...

    s32k312之Relocating the stack in DTCM

    ### S32K312之Relocating the stack in DTCM #### 知识点一:S32K312概述 S32K312是一款高性能、低功耗的微控制器(MCU),适用于汽车电子领域中的各种应用。它支持多种通信接口,并具备强大的计算能力和丰富的...

    Relocating Windows7 User Folder and Profiles

    ### 在Windows 7中迁移用户文件夹和配置文件的知识点详解 #### 背景介绍 随着技术的发展和个人计算需求的变化,很多用户和系统管理员可能会遇到需要将Windows 7默认的用户文件夹(通常位于`C:\Users`)迁移到另一块...

    SSD7 选择题。Multiple-Choice

    The foreign key in a table T1 _____ the same _____ as the corresponding primary key in table T2. must have, name need not have, name must have, domain (a) I, II, and III (b) I and II (c) ...

    relocating-to-berlin, q& A 关于重新定位到柏林,德国.zip

    relocating-to-berlin, q& A 关于重新定位到柏林,德国 到柏林q& A 关于重新定位到柏林,德国。 所有答案都基于我们自己的经验。:我如何提交一个问题?请创建问题或者请求请求。 英文 ( 如果你很难用英语表达自己,...

    AT24CXX.rar_AT89C2051_Code Name_at24cxx

    AT89C1051 by relocating or resizing the buffer and stack to fit into the smaller amount of RAM available in the AT89C1051. Note that the minimum size of the buffer is determined by the page size of...

    relocating:使用Multilateration和粒子群优化(PSO)来解析对象位置

    通过relocating您将能够知道物体在空间中的位置。 所有信息您来自一组无线电台(信标),这些无线电台可以提供有关该对象的单条信息:(由于测量误差)该对象与他本人的近似距离(圆周半径)。 这意味着,通过将...

    SPI_TEST.rar_51 spi_Modified_spi ram

    This version of the code is compatible only with the AT89C2051... work with the AT89C1051 by relocating or resizing the buffer and stack to fit into the smaller amount of RAM available in the AT89C1051.

    relocating-to-berlin:关于搬迁到德国柏林的问答

    搬到柏林 关于搬迁到德国柏林的问答。 所有答案均基于我们自己的经验。 我该如何提出问题? 请创建一个或拉取请求。 可以用英语接受问题(如果您很难用英语表达自己的意思,我们也可以考虑使用俄语)。...

    一种能耗―性能协调优化的虚拟机重放置策略 (2016年)

    以降低能耗和保证虚拟机的服务质量为目标,提出一种能耗―性能协调的虚拟机重放置优化算法,即能耗―性能优化配合降序最佳适应算法(energy-performance awareness best fit descending virtual machine relocating,...

    simplefs:从头开始的一个简单的,内核空间的磁盘文件系统

    《构建内核空间的简单磁盘文件系统:深入理解simplefs》 在计算机科学领域,文件系统是管理和存储数据至关重要的部分。它负责组织、命名和检索存储在磁盘上的文件,是操作系统与硬件之间的桥梁。...

    cfdisk命令 用于磁盘分区

    cfdisk是用来磁盘分区的程序,它十分类似DOS的fdisk,具有互动式操作界面而非传统fdisk的问答式界面,您可以轻易地利用方向键来操控分区操作。cfdisk指令是一个基于鼠标的、用于硬盘分区的程序。...

    GB/T 11457-2006 信息技术 软件工程术语

    在软件工程术语中,明确了一些专业词汇,如“绝对汇编程序”(absolute assembler),它是指产生绝对代码的汇编程序,与“重定位汇编程序”(relocating assembler)形成对比。这些术语的定义和区分有助于在软件开发...

    khook:通过 devmem 将动态链接的代码加载到内核空间

    胡克 通过 /dev/mem 将动态链接的代码加载到内核空间 示例输出 安慰: [KHOOK] 80200000-88dfffff [KHOOK] kmem_phys=0x80200000-0x88dfffff [KHOOK] kmem_virt=0xc...[GRUB] (modules) relocating to 0x836a8 [G

    深入理解计算机系统(英文版)

    1.1 Information isBits inContext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Programs areTranslated byOtherPrograms intoDifferent Forms . . . . . . . . . . . . . . . 3 1.3 ...

    uboott移植实验手册及技术文档

    @ get read to call C functions (for nand_read()) ldr sp, DW_STACK_START @ setup stack pointer mov fp, #0 @ no previous frame, so fp=0 @ copy U-Boot to RAM ldr r0, =TEXT_BASE mov r1, #0x0 mov r2...

Global site tag (gtag.js) - Google Analytics