How to read a .data file encoded using NSKeyedArchiever iPhone - 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

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);

What is the lifeCycle of a .plist file

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.

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.

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.

Plist not saving from dictionary (to Documents)

I've been trying to save a plist of a NSDictionary to my app's Documents folder. I haven't tried this on the device yet but I'd like it to work on the simulator for testing purposes. The [self createDictionaryFromChoreList] method just creates a NSDictionary from some data in another class of mine. I've pretty much copied/pasted this code from the web documents and when I go to see if the file was saved or not, I find that it isn't. Here is the method block.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistName = [[NSString alloc] initWithFormat:#"%#chores.plist", self.firstName];
NSString *path = [documentsDirectory stringByAppendingPathComponent:plistName];
NSDictionary *choresDictionary = [[NSDictionary alloc] initWithDictionary:[self createDictionaryFromChoreList]];
[choresDictionary writeToFile:path atomically:YES];
Any help is greatly appreciated. Thanks in advance.
-S
You should also capture the BOOL returned by writeToFile:atomically:. That will tell you if the write succeeded or not.
Also, are you sure you are looking in the right documents folder? If you have more than one app in the simulator its easy to open the wrong app's documents folder in the Finder. I did that once and it cost me a couple of hours of frustration.
Edit01:
writeToFile:atomically: returning false explains why no file exist. The simplest explanation is that something in the dictionary is not a property list object.
From the NSDictionary docs:
This method recursively validates that
all the contained objects are property
list objects (instances of NSData,
NSDate, NSNumber, NSString, NSArray,
or NSDictionary) before writing out
the file, and returns NO if all the
objects are not property list objects,
since the resultant file would not be
a valid property list.
It just takes one non-plist object buried deep in a dictionary to prevent it from being converted to a plist.
Don't forget serialize the plist data:
Here is a snippet of code that I use for writing information to a plist
NSString *errorString;
NSData *data = [NSPropertyListSerialization dataFromPropertyList:plistDict
format:NSPropertyListXMLFormat_v1_0
errorDescription:&errorString];
[plistDict release];
if (!data) {
NSLog(#"error converting data: %#", errorString);
return NO;
}
if ([data writeToFile:[XEraseAppDelegate loadSessionPlist] atomically: YES]) {
return YES;
} else {
NSLog(#"couldn't write to new plist");
return NO;
}
This is something I whipped up really quickly and it correctly writes a plist directory of name and company to the documents directory. I have a feeling your dictionary creation method might have an issue. Try this out for yourself, then add your code and make sure it works.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *plistDirectory = [paths objectAtIndex:0];
NSString *plistPath = [plistDirectory stringByAppendingPathComponent:#"userCompany.plist"];
NSArray *userObjects = [[NSArray alloc] initWithObjects:#"Joe", #"Smith", #"Smith Co", nil];
NSArray *userKeys = [[NSArray alloc] initWithObjects:#"First Name", #"Last Name", #"Company", nil];
NSDictionary *userSettings = [[NSDictionary alloc] initWithObjects:userObjects forKeys:userKeys];
[userSettings writeToFile:plistPath atomically:YES];
Is it correct, that the name of file your writing to is:
SOEMTHINGchores.plist?
Created via:
NSString *plistName = [[NSString alloc] initWithFormat:#"%#chores.plist", self.firstName];
Also, what is the output of:
[choresDictionary print];
Some additional info would help to debug this.
Where exactly are you looking for the file?
I have the exact same code and it works fine for me.
Just that I have to dig deep to get the file. Something like:
/Users/myUserName/Library/Application Support/iPhone Simulator/User/Applications/0E62A607-8EEB-4970-B198-81CE4BDDB7AA/Documents/data.plist
And the HEX number in the path changes with every run. So I print the file path with every run.
Insert a break point at
NSDictionary *choresDictionary = [[NSDictionary alloc] initWithDictionary:[self createDictionaryFromChoreList]];
now when you step out drag your mouse over choresDictionary and check in the tooltip that its size is not 0x0 or you can simply do an NSLog of the choresDictionary
like NSLog(#"%#",choresDictionary); I think your dictionary has 0 key key value pairs thats why you are getting null into your documents folder.
Thanks,
Madhup
I was running into this issue as well. In my case it turned out that I was using NSNumbers for keys - which is not valid.