IPhone Core Data Persistence & Lifecycle Question - iphone

Whenever I build & run my program I notice that a new directory gets created in:
/Users/Username/Library/Application Support/iPhone Simulator/User/Applications
Therefore, there's no way for me to persist core data between application builds. The way I thought to get around this issue (from a testing point of view) was to just use the iphone simulator to exit the application by pressing the circular menu button and re-run my app. I.e., not build it but just rerun it via the simulator to see if the data is persisted in core data.
Now I wanted to check if the data is persisting each time the application is run. The event that I'm using is:
(void)applicationDidFinishLaunching:(UIApplication *)application
But it only fires after I build & run the application but doesn't get fired each time i restart the application - via iphone simulator (i.e., pressing menu button then rerunning my program).
Is there another event I should be using?? If I had an event that gets fired every time the application loaded I think I could just check to see if core data has data in it, if it doesn't i just populate it with an xml file to initialize it, if it does have data I don't do anything. Sound right? If so, what is that event called?

-applicationDidFinishLaunching: will be called EVERY time your app launches, whether from the debugger, hitting the icon in the Springboard (launcher), or either of these on the device.
On the sim, a folder in the .../Applications directory is created for your app, and any data stored in there will be persisted. The actual name of the folder will change each time you build-and-run your app, but the contents will remain the same, so you can store data there.

Ben's right. The reason you aren't seeing -applicationDidFinishLaunching is because the debugger doesn't run when you launch from the simulator, the method is still firing.
It sounds like you're still early in the Core Data development process. You'd probably benefit from turning on Lightweight Migration.
NSError *error;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![psc addPersistentStoreWithType:<#Store type#>
configuration:<#Configuration or nil#> URL:storeURL
options:options error:&error]) {
// Handle the error.
}
Instead of having to destroy your data store each time you make changes to the data model, this should allow Core Data to intelligently update the model for you.
Sorry this is a little off-topic, but I've spent a lot of time erasing and re-loading my data store because I didn't realize there was such a thing as this lightweight migration.

As vfn writes, you either need to attach the debugger or persist the log values to the disk.
I was doing OAuth and that requires the simulator to leave the app and do some authentication is Safari and then Safari will reopen the app using an URL Scheme. This meant I could not get a log of the different authentication steps logged after the app had quit.
Anyways, I wrote this class that will log messages to "log.txt" situated in ~/user*/library/application support/iPhone Simulator/user/yourapp*/documents
*user and yourapp is of course variable names.
//
// LogFile.m
//
//
// Created by RickiG on 11/30/09.
// Copyright 2009 www.rickigregersen.com.. All rights reserved.
//
#import "LogFile.h"
#implementation LogFile
+ (void) stringToLog:(NSString *) str {
NSDate *now = [NSDate date];
NSDateFormatter *logTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[logTimeFormatter setDateFormat:#"HH:mm:ss"];
NSString *timeStr = [NSString stringWithFormat:#"%#", [logTimeFormatter stringFromDate:now]];
NSString *logMsg = [NSString stringWithFormat:#"%#\n%#\n\n", timeStr, str];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:#"log.txt"];
NSData *dataToWrite = [[NSString stringWithString:logMsg] dataUsingEncoding:NSUTF8StringEncoding];
// Check if file exists
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:path]) { // Returns a BOOL
NSData *dataFromFile = [[NSData alloc] initWithContentsOfFile:path];
NSMutableData *combinedDataToWrite = [NSMutableData dataWithData:dataFromFile];
[combinedDataToWrite appendData:dataToWrite];
[combinedDataToWrite writeToFile:path atomically:YES];
[dataFromFile release];
} else {
[fileManager createFileAtPath:path contents:dataToWrite attributes:nil];
}
}
#end

Have you tried working with
-(void)applicationDidBecomeActive {
}

Related

Remote wipe out application in iDevice

How to remote wipe out data/application from iDevice [iPod Touch, iPhone or iPad] ?
Possible solutions are as follow.
Configure "Find My iPod" on your iPod
Make server call and check is device was reported as stolen ? If yes then call exit(0) function and wipe out data and app.
I used second solution to wipe out data from app. I used following 2 methods for that.
-(NSString *)getDatabasePath {
NSArray *subDir = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self applicationAppSupportDirectory] error:nil];
NSString *path = [[[self applicationAppSupportDirectory] stringByAppendingPathComponent:[subDir lastObject]]
stringByAppendingPathComponent:#"xyz.sqlite"];
return path ;
}
-(void)deleteDatabase {
NSFileManager *manager = [NSFileManager defaultManager] ;
NSError *error = nil ;
NSString *databasePath = [self getDatabasePath];
if ([manager fileExistsAtPath:databasePath]) {
[manager removeItemAtPath:databasePath error:&error] ;
}
debug(#"%#",error);
if (error) {
[Utility showAlertViewWithTitle:#"Error" andMessage:error.localizedDescription];
}
}
-(void)deleteApplication {
exit(0);
NSString *appPath = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] ;
NSLog(#"%#",appPath);
}
I deleted application folder but still Application Logo is there on my iDevice.
Is this a right way to wipe out my app ?
Will apple reject my app for this ?
Why appLogo is still there as i entirely delete app folder ?
Apple won't allow you to use exit(0). You can probably wipe the user data though, but you will have make sure the application can still be used after that (I.e. bring the app back into the state of first launch).
For the reporting stolen part: you will have to create your own web UI or similar for this, as Apple currently doesn't allow you to access that kind of iCloud information from within a third party app.

Clear Web App Local Storage on IOS 6

I'm a web app developer trying to test my app, but Apple has changed the way they save web app data when you add it to the home screen.
How can I clear my web app's local storage so I can see updates to my code?
iOS Apps are stored in a sandbox. So every application has its own directory and working space.
In that working space all data of the application gets stored. This includes documents, library files, temporary files, the application bundle, as well as the preferences file.
When a user chooses to delete an app, the whole sandbox gets removed, including those preferences.
Here are some Solutions for Handling App sandbox data
Deleting all the files in the iPhone sandbox
NSFileManager *fileMgr = [[[NSFileManager alloc] init] autorelease];
NSError *error = nil;
NSArray *directoryContents = [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error];
if (error == nil) {
for (NSString *path in directoryContents) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:path];
BOOL removeSuccess = [fileMgr removeItemAtPath:fullPath error:&error];
if (!removeSuccess) {
// Error handling
...
}
}
} else {
// Error handling
...
}
Clear Safari Cache
Clear UIWebView Cache
// Flush all cached data
[[NSURLCache sharedURLCache] removeAllCachedResponses];
Reference
Hope this helps!

When is the iPhone app cache is cleared?

I'm working on an app that lets users record voice (among other things) to the Documents directory of the app. But when I'm recording the voice, I'm recording to the caches directory of the app and then after the user says "Okay, save this one", then I'm coping it to the Documents directory. So far all these work. But if I try to delete the data file in cache, or when I try to move it, I get problems.
So my question is, shall I just leave the data in cache so that iOS will handle it or do I need to manually delete the files in cache. If so how would I go about doing it. This is the code I have so far (which doesn't work)
NSFileManager *fm = [NSFileManager defaultManager];
NSString *directory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSError *error = nil;
BOOL success = [fm removeItemAtPath:[NSString stringWithFormat:#"%#%#", directory, currentEntry.audioFileURL] error:&error];
if (!success || error) {
// it failed.
NSLog(#"it failed to delete!!! %# %#", error, [error userInfo]);
} else {
NSLog(#"Deleted... yipee... !!!");
}
I think the problem is that your path is not correct. Always use the
- (NSString *)stringByAppendingPathComponent:(NSString *)aString
method of NSString.
You can try printing out the path you get now (maybe a backslash is missing), but anyway you should use the method I described.
UPD: Another thing is that NSCachesDirectory is actually never cleaned up. Use NSTemporaryDirectory() if you want automatic cleaning.

Clear Absolute Cache on Application close Ipad app

I am saving Images in NSCachesDirectory in a App. At the end of app execution i would like to clear all temporary cache. Is there a way to force clear all cache on application exit. I do realise the local folder keeps cache for 3 days..but my requirement is to force clear the Cache. Thx
This code should do the trick, just substitute the name of your cache directory...
NSString *cacheDirectoryName = [self getCacheDirectoryName];
NSArray *items = [fileManager directoryContentsAtPath:cacheDirectoryName];
for (NSString *item in items)
{
NSString *path = [cacheDirectoryName stringByAppendingPathComponent:item];
NSError *error = nil;
[fileManager removeItemAtPath:path error:&error];
[error release];
}
Then call the code in your AppDelegate applicationWillTerminate method.

Core Data quesition

I'm trying to write two applications (iphone and desktop) to achieve what's been described in the following link:
core-data-is-it-possible-to-build-a-desktop-app-to-create-the-data-model-for-an
Ok. So I've created a very simple desktop app the has a single entity named Client with a string attribute field called name. I've also generated the corresponding Model class.
I've run the app added a couple of client names to the list and saved the file (as Testing.sqlite).
Now in my equivalent iphone app I'm attempting to load the file. I've generated the app initially using one of the application templates and included Core Data. NB: I've mirrored the Client entity and generated the corresponding Model class.
I've gone into my "application delegate" class and amended the persistentStoreCoordinator method to reference my "Testing.sqlite" file i.e.
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"Testing.sqlite"]];
I've also copied the saved desktop app file into the expected location i.e.
~/Library/Application Support/IPhone Simulator/User/... etc.
So now in theory at least each of the two apps should be the same.
However when I'm attempting to load the data from the it always seems to be empty. My code looks a little like this:
// fetch the delegate.
TestingAppDelegate *app = (TestingAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = [app managedObjectContext];
// construct the request.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Client" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// execute the request.
NSError *error;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
if (results == nil) {
// Handle the error.
NSLog(#"No data loaded");
}
NSLog(#"Returned: %#", results);
// finally release
[results release];
[request release];
I can't seem to figure out what's going wrong. Any tips or suggestions would be totally appreciated.
When I've looked at the instance of the persistanceStoreCoordinator, managedObjectContext, resulting array (NSArray) whilst debugging I can see that it seems to contain 0 records for all of these. So I'm confused.
NB: The Testing.sqlite file contains entries.
Thanks in advance,
Matt
Simply copying the sqlite database file will not work when using Core Data.
You need to fully replicate the persistent store you created in your desktop application.
However, this may be a problem related to the fact that Core Data is not seeing your database file even though you copied it. Try the following:
1) add your database file to your project in the resources group
2) use this method to actually copy your database file in place
- (NSString *) initialize_db {
NSString *DATABASE_RESOURCE_NAME = #"testing";
NSString *DATABASE_RESOURCE_TYPE = #"sqlite";
NSString *DATABASE_FILE_NAME = #"testing.sqlite";
// copy the database from the bundle if necessary
// look to see if DB is in known location (~/Documents/$DATABASE_FILE_NAME)
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolderPath = [searchPaths objectAtIndex: 0];
NSString *dbFilePath = [documentFolderPath stringByAppendingPathComponent: DATABASE_FILE_NAME];
[dbFilePath retain];
if (! [[NSFileManager defaultManager] fileExistsAtPath: dbFilePath]) {
// didn't find db, need to copy
NSString *backupDbPath = [[NSBundle mainBundle]
pathForResource:DATABASE_RESOURCE_NAME
ofType:DATABASE_RESOURCE_TYPE];
if (backupDbPath == nil) {
// couldn't find backup db to copy, bail
NSLog (#"couldn't init db");
return NULL;
} else {
BOOL copiedBackupDb = [[NSFileManager defaultManager]
copyItemAtPath:backupDbPath
toPath:dbFilePath
error:nil];
if (! copiedBackupDb) {
// copying backup db failed, bail
NSLog (#"couldn't init db");
return NULL;
}
}
}
return dbFilePath;
}
Once you have copied the database file, you have its file path returned, and you use it to actually open the database.