Skip to content

Instantly share code, notes, and snippets.

@walm
Created May 1, 2012 06:55
Show Gist options
  • Save walm/2565759 to your computer and use it in GitHub Desktop.
Save walm/2565759 to your computer and use it in GitHub Desktop.
PERSISTENT LOCALSTORAGE NATIVE SOLUTION for phonegap (fork of http://pastebin.com/5881768B)
/*
*
* PERSISTENT LOCALSTORAGE NATIVE SOLUTION for phonegap (tested on 1.3)
* iOS 5.1 puts LocalStorage in a vulnerable location (Libary/Caches). This will copy it to
* the documents folder as "appdata.db" so that it will be appropriately backed-up and not
* overwritten. If "appdata.db" doesn't exist, localStorage will not be overwritten.
* Also, upon application suspend (resignActive) or termination, localStorage is saved, so
* there should not be any chance that changes to localStorage won't be persisted. [[ short of a power-cycle ]]
*
* The following should be placed in AppDelegate.m. Note that it //partially// replaces
* webViewDidStartLoad:. The remainder of webViewDidStartLoad: (as in phonegap 1.3) is below,
* replace/remove as appropriate
*
* @Author: Kerri Shotts (2012)
* @License: MIT License
*
* Notes: USES ARC. IF USING MRC, apply the appropriate releases.
*
* Based partially on http://gauravstomar.blogspot.com/2011/08/prepopulate-sqlite-in-phonegap.html
*
*/
- (BOOL)fileExists: (NSString*) theFile
{
NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager fileExistsAtPath:theFile];
// MRC: make sure to release
}
- (void)copyFile:(NSString*) sourceFile to:(NSString*) targetPath withName:(NSString*) targetFile
{
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager createDirectoryAtPath:targetPath withIntermediateDirectories:YES attributes:nil error:NULL];
NSString *fullTargetFile = [targetPath stringByAppendingPathComponent:targetFile];
NSLog(@"Source File for Copy: %@", sourceFile);
NSLog(@"Target File for Copy: %@", fullTargetFile);
if ( [self fileExists:fullTargetFile] )
{
// remove the file first. (Ick! I wish there was a better way...
if ( [fileManager removeItemAtPath:fullTargetFile error:nil] == YES )
{
NSLog (@"Target successfully removed.");
}
else
{
NSLog (@"Target could not be removed prior to copy. No copy will occur.");
return;
}
}
if ( [fileManager copyItemAtPath:sourceFile toPath:fullTargetFile error:nil] == YES)
{
NSLog(@"Copy successful.");
}
else
{
NSLog(@"Copy unsuccessful.");
}
// MRC: don't forget to release fileManager where necessary!
}
- (BOOL)isIOS5_1OrHigher
{
// based on: http://stackoverflow.com/a/9320041
NSArray *versionCompatibility = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
if ( [[versionCompatibility objectAtIndex:0] intValue] > 5 )
{
return YES; // iOS 6+
}
if ( [[versionCompatibility objectAtIndex:0] intValue] < 5 )
{
return NO; // iOS 4.x or lower
}
if ( [[versionCompatibility objectAtIndex:1] intValue] >= 1 )
{
return YES; // ios 5.<<1>> or higher
}
return NO; // ios 5.<<0.x>> or lower
}
- (void)copyPersistentStorageToLocalStorage
{
// build localStorage path: ~/Library/WebKit/LocalStorage/file__0.localstorage (for iOS < 5.1)
// ~/Library/Caches/file__0.localstorage (for iOS >= 5.1 )
NSString *localStoragePath;
if ( [self isIOS5_1OrHigher] )
{
// for IOS >= 5.1
localStoragePath =
[
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:@"Caches"
];
}
else
{
// for IOS < 5.1;
localStoragePath =
[
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:@"WebKit/LocalStorage"
];
}
// build persistentStorage path: ~/Documents/appdata.db
NSString *persistentStoragePath =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *persistentStorageFile = [persistentStoragePath stringByAppendingPathComponent:@"appdata.db"];
// does the persistent store exist?
if ([self fileExists:persistentStorageFile ])
{
// it does, copy it over localStorage
NSLog(@"Copying persistent storage to local storage.");
[self copyFile:persistentStorageFile to:localStoragePath withName: @"file__0.localstorage"];
}
else
{
NSLog(@"No persistent storage to copy. Using local storage only.");
}
}
- (void)copyLocalStorageToPersistentStorage
{
// build localStorage path: ~/Library/WebKit/LocalStorage/file__0.localstorage (for iOS < 5.1)
// ~/Library/Caches/file__0.localstorage (for iOS >= 5.1 )
NSString *localStoragePath;
if ( [self isIOS5_1OrHigher] )
{
// for IOS >= 5.1
localStoragePath =
[
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:@"Caches"
];
}
else
{
// for IOS < 5.1;
localStoragePath =
[
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
stringByAppendingPathComponent:@"WebKit/LocalStorage"
];
}
NSString *localStorageFile = [localStoragePath stringByAppendingPathComponent:@"file__0.localstorage"];
// build persistentStorage path: ~/Documents/appdata.db
NSString *persistentStoragePath =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// does the local store exist? (it almost always will)
if ([self fileExists:localStorageFile ])
{
// it does, copy it over persistent Storage
NSLog(@"Copying local storage to persistent storage.");
[self copyFile:localStorageFile to:persistentStoragePath withName:@"appdata.db"];
}
else
{
NSLog(@"No local storage to copy. Using local storage only.");
}
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// move the local storage data to persistent storage
// while we're resigning so that we know our data is safe...
[self copyLocalStorageToPersistentStorage];
return;
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// move the local storage data to persistent storage
// while we're terminating so that we know our data is safe...
[self copyLocalStorageToPersistentStorage];
return;
}
- (void)webViewDidStartLoad:(UIWebView *)theWebView
{
[self copyPersistentStorageToLocalStorage];
//
// END Persistent LocalStorage solution. Remainder of webViewDidStartLoad: should be used.
//
return [ super webViewDidStartLoad:theWebView ];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment