What is the lifeCycle of a .plist file - iphone

I am totally confused while using a plist file.
Can anyone explain me the lifecycle of the .plist file.
If I create a .plist file programmatically and add some data in it.
and if i close my app (completely not deleting it) does my .plist file will get lost and i have to recreate it.?
I have this code
-(void)WriteFileToPlist:(int) num
{
//write everything in the plist
NSString *errorDesc;
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:strArray format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if (plistData) {
[plistData writeToFile:[self savePathForFile:num] atomically:YES];
}
}
//save the path
-(NSString *) savePathForFile:(int) num
{
NSArray *pathArray =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"myPlist%d.plist",num]];
}
question is where the file myPlist get stored. closing the app will delete this plist or not.??

It's simply a file stored on the device. If you save it in the right folder (for example, not a Cache folder) it'll stay there, just like any other file you can save.

Related

How to browse the iPhone simulator

my app is creating a CSV file out of a db. I want to browse and open the file to test. How do I access the iphone simulator's storage ?
All data of the Simulator is stored as local files on your Mac.
The path for the user data of iOS apps in the Simulator is:
~/Library/Application Support/iPhone Simulator/[OS version]/Applications/[appGUID]/
You'll want to print out the location of where you store your file when you run the app in the simulator.
You can use this code to get the location of the Library/Cache folder here:
-(NSString *) mediaPathForFileName:(NSString *) fileName
{
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [directoryPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", cachesDirectory, fileName];
return filePath;
}
Pass in a random file name like "test.txt":
// somewhere in your viewDidLoad method
[self mediaPathForFileName:#"test.txt"];
This will print out the path to your app Library/Cache folder.
you need get the path of that file by using NSLog and then user Shift+Cmd+G to go to that path.
pritn this path
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

Adding data to the plist dynamically and populating the tableview cells

I am developing an application where i have created the plist, and i am adding data to it..but what is happening is that everytime the data is overwritten and the previous data is lost. I mean suppose i add one name called rocky, next time when i add rock, rocky gets overwritten with rock, but what i want is my plist should contain both rocky and rock and so on...I am adding the data in plist by user entry....
here is my code below..
-(IBAction) myplist:(id) sender//the data is saved in a plist by clicking on this button
{
NSLog(#"mylist Clicked");
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:searchLabel.text];
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"Data.plist"];
// This writes the array to a plist file. If this file does not already exist, it creates a new one.
[array writeToFile:plistPath atomically: TRUE];
}
I think this will serve your purpose with a slight modification to your code.
NSLog(#"mylist Clicked");
NSMutableArray *array = [[NSMutableArray alloc] init];
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"Data.plist"];
//This copies objects of plist to array if there is one
[array addObjectsFromArray:[NSArray arrayWithContentsOfFile:plistPath]];
[array addObject:searchLabel.text];
// This writes the array to a plist file. If this file does not already exist, it creates a new one.
[array writeToFile:plistPath atomically: TRUE];
Try to use a sequence to store data to pList.
1., retrieve old data from pList into a NSMutableDictionary/NSMutableArray
2., add a new record into the NSMutableDictionary/NSMutableArray
3., write to file
You cant append data to Plist. Since you are doing writeToFile each time , the plist file gets re-written. So the data u stored initially will not be there in it. The only other way to achieve wat u desire is to retrieve the array of data from the plist. Then add ur new data object to the array. Write the plist file to disk again with the new appended array.
Hope this helps.

How to read a .data file encoded using NSKeyedArchiever iPhone

I use NSKeyedArchiver to archive data in my iPhone app into a .data. Long story, short, I lost all my data. I use "iPhone back up extractor" and it works great. I found a .data file for my app.
To be clear, I found a .data file and I would to open and see what the contents look like. I understand no software (Ex: notepad) might be able to read that file and I may have to use Xcode. If you know of any way, Xcode/notepad/someProgram, please let me know.
This is the code that I implement when I build the app:
- (NSString *)locPath {
return pathInDocumentDirectory(#"tableArray.data");
}
- (void)archieve{
// Get the path to the document directory
NSString *path = [self locPath];
// grab the array
NSMutableArray *tableArray = [someViewController tableArray];
// archive the array to file
[NSKeyedArchiver archiveRootObject:tableArray toFile:path];
}
This code is called during applicationWillTerminate, applicationDidEnterBackground, etc...
The data is restored/called upon in the didFinishLaunchingWithOptions like this:
// Get the path to the document directory
NSString *path = [self locPath];
// Unarchive .data into an array
NSMutableArray *tableArray = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
Any help is appreciated! Thanks!!!
PS: Link for iPhone back up extractor is http://supercrazyawesome.com/
The easiest way I found is to get the document directory using this code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSLog(#"Directory: %#", dir);
In there, the Documents dir will contain the .data file

Read/Write to a plist file that comes bundled with the app

I am building an add-on to my app where the user can search for an item in a list that is pre-populated with data from a .plist file. It is an NSDictionary. If the term, the user searched for, does not exist, the user can tap a + button and add it so it is there the next time.
First of I thought it would be as easy as using the NSUserDefaults, but a few problems arises.
To have the list included I must place it in the bundle, but if it is there I can not add new key/value pairs to it. This I can only do with files situated in the Documents folder.
So I guess I have to bundle the plist, then on first run I'll move it to the documents folder and access it there.
This opens up the problem when I need to update the app, I guess it will overwrite the values the user put in.
Is there a secure, easy-understandable, right way to achieve the functionality I describe?
Thanks for any help given:)
Edit: **** the actual approach, as suggested by TheSquad and TomH *****
+ (NSMutableDictionary*) genericProducts {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"GenericProducts.plist"];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *bundlePlistPath = [bundlePath stringByAppendingPathComponent:#"GenericProducts.plist"];
if([fileManager fileExistsAtPath:documentPlistPath]){
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return documentDict;
} else {
NSError *error;
BOOL success = [fileManager copyItemAtPath:bundlePlistPath toPath:documentPlistPath error:&error];
if (success) {
NSMutableDictionary *newlySavedDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return newlySavedDict;
}
return nil;
}
}
And for adding a new product to the list:
+ (void) addItemToGenericProducts:(NSString*) newProduct {
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"GenericProducts.plist"];
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
[documentDict setObject:newProduct forKey:[MD5Checksum cheksum:newProduct]];
[documentDict writeToFile:documentPlistPath atomically:YES];
}
I had the same thoughts with my sqlite database...
I end up doing exactly that, copy the bundled file into documents in order to be able to modify it.
What I have done is checking at each startup if the file exist, if it does not, copy it.
If you do an update of your App, the documents folder will not be touch, this means the copied file from the previous version will still be present.
The only issue is that if you want your plist to be upgraded you will have to handle that in your application. If you have to do so I suggest you use the NSUserDefault to check if a previous version of the app existed before...
The contents of the documents directory is not altered when an application is updated.
The contents of the documents directory are deleted when the user deletes the app.
When the app is run the first time write a flag to NSUserDefaults. On subsequent runs of the app, check for existence of the flag. (alternatively, you can just check for existence of the plist in he documents directory)

IPhone FIlewrappers and document packages?

Suppose I have an model object class Box. In my Box class I add images references (png), audio (mp3) etc...
Rather than store them as NSData it seems better to reference the paths to the files...to save memory.
I would like archive this Box class. On the desktop we would use Document Packages (NSFilewrapper). But this class is not part of the Iphone OS.
Any suggestions on archiving this class and including all the files as 'document package'? This is similar to the way Applications appear as a file but are actually a folder...
Thanks!
If you really need to save the objects in Box, I would load them into an NSDictionary and the write that out:
Note: this is untested/non-production code intended to be a starting point only.
- (BOOL)saveBox:(Box*)aBox;
{
NSMutableDictionary *boxDict = [NSMutableDictionary dictionaryWithCapacity:10];
// Add contents of box to dictionary (exercise left up to original poster)
// boxDict is now populated
// write dictionary to apps document directory.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
if (!documentsDirectory) {
NSLog(#"Documents directory not found!");
return NO;
}
// Assumes Box class has name property
NSString *outputFile = [documentsDirectory stringByAppendingPathComponent:[aBox name]];
return [boxDict writeToFile:outputFile atomically:YES];
}
This could easily be modified to return the name of the file, etc. based on your needs.