I am using the code found in this post: Mulitple Arrays From Plist, with the same plist formatting.
This works successfully, however I do not know how to save the created arrays back into a plist, in the same format.
How would I achieve this?
EDIT: It is not so much the saving that I need, but the forming of the data to save.
The plist is an array of dictionaries with strings and their corresponding keys.
All the strings with a certain key are put into an array of their own.
How would I put that array back into the correct positions in the array of dictionaries, ready to save?
Here's the simplest way:
NSDictionary* dict = ...;
[dict writeToFile:#"..." atomically:YES];
See the documentation for -writeToFile:atomically:.
Don't forget to create myPlistFile.plist and add it in your application resource folder.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
you could scan paths here and search myPlistFile.plist using for loop.
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"myPlistFile.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath: plistPath])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"myPlistFile" ofType:#"plist"];
[[NSFileManager defaultManager] copyItemAtPath:bundle toPath:plistPath error:&error];
}
[myDict writeToFile:plistPath atomically: YES];
And conversely, to load a NSDictionary FROM a file:
+ (id)dictionaryWithContentsOfFile:(NSString *)path;
Related
hello I am trying to create a text file that will then store some data
- (IBAction)saveUser:(id)sender{
NSString *name = [nameField stringValue];
NSString *weight = [weightField stringValue];
NSDate *date = [datePick dateValue];
}
I want to be able to create a file that stores the following information and uses the name field as the name of the file. I also want to be able to load the file and read that data from it
Any help is appreciated
Thanking You
This is quite simple. But you might want to look into NSMutableDictionary instead. Both NSString and Dictionary have methods writeToFile:#"filename.txt".
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:[nameField stringValue] forKey:#"name"];
[dict setValue:[weightField stringValue] forKey:#"weight"];
[dict setValue:date forKey:#"date"];
[dict writeToFile:name atomically:YES];
you read from the file the same way,
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:name];
As simple as it gets
I think you may get some informations from class NSFileManager, such as like this,
[fileManager createFileAtPath:filePath contents:contentData attributes:NULL];
the contentData is NSData, and it includes the content of what you want to save, the filename is in filePath that you need to set.
Thanks!
I use the following code to copy a Resources plist file into the documents directory:
BOOL success;
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Test-Info.plist"];
success = [fileManager fileExistsAtPath:filePath];
if (!success) {
NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingFormat:#"Test-Info.plist"];
success = [fileManager copyItemAtPath:path toPath:filePath error:&error];
NSLog(#"Test-Info.plist successfully copied to DocumentsDirectory.");
}
I get the success message, which is great. I'm assuming it's been copied correctly into the documents folder.
However when I then try to read and write to the saved plist file it returns null:
Key entry in Test-Info.plist:
Key: EnableEverything
Type: Boolean
Value: YES
Write code:
NSString *adKey = #"EnableEverything";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *path = [documentsDirectoryPath stringByAppendingPathComponent:#"Test-Info.plist"];
NSMutableDictionary *plist = [NSDictionary dictionaryWithContentsOfFile: path];
NSString *enableEverything = [[plist valueForKey:adKey] stringValue];
NSLog(#"****** EXISTING: %# ******", enableEverything); // returns (null)
// Disable in plist.
[plist setValue:0 forKey:adKey]; // will this work?
[plist writeToFile:path atomically:YES]; // this doesn't throw an error?
NSString *enableEverything1 = [[plist valueForKey:adKey] stringValue];
NSLog(#"****** NOW: %# ******", enableEverything1); // returns (null)
Output:
****** EXISTING: (null) ******
****** NOW: (null) ******
My question is why are they (null) when they exist within the plist file?
You are trying to mutate an immutable object.
You need a NSMutableDictionary.
IE
NSMutableDictionary *plist = [[NSDictionary dictionaryWithContentsOfFile: path] mutableCopy];
Also check, if the plist object isnt nil, as any messages can be send to nil without raiing an error. this wouldnt fail, also nothing actually happens.
[plist setValue:0 forKey:adKey]; // will this work?
[plist writeToFile:path atomically:YES]; // this doesn't throw an error?
as the source path is nil, you are most like not copying the file during compilation bundling. drag it here:
Try this for nsbundle path for resource
NSString *path= [[NSBundle mainBundle] pathForResource:#"SportsLogo-Info" ofType:#"plist"];
Try allocating
NSMutableDictionary *plist = [[NSMutableDictionary alloc] initWithDictionary:[NSDictionary dictionaryWithContentsOfFile:path]];
Also check if the file has been copied or not. Go to Library=>Application Support=>iPhone Simulator=>folder named your version of simulator iOS=>Applications=>Find the right folder of your project=>Documents see if the plist file is there
I am using plists to save/load an NSMutableArray,
the code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *prsPath = [documentsDirectory stringByAppendingPathComponent:#"records.plist"];
prs = [[NSMutableArray alloc] initWithContentsOfFile:prsPath];
when I am using the last sentence of code somewhere else in my code it says: "prsPath" undeclared. (I am loading my code in ViewDidLoad) When I add an Object it doesn't save it, it doesn't even show up. (Loading the last sentence on add)
I'm using this method and it's work 100%
- (void) writeToPlist: (NSString*)fileName withData:(NSMutableArray *)data
{
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:fileName];
[data writeToFile:finalPath atomically: YES];
/* This would change the firmware version in the plist to 1.1.1 by initing the NSDictionary with the plist, then changing the value of the string in the key "ProductVersion" to what you specified */
}
and this method for reading from plist file:
- (NSMutableArray *) readFromPlist: (NSString *)fileName {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *finalPath = [documentsDirectory stringByAppendingPathComponent:fileName];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:finalPath];
if (fileExists) {
NSMutableArray *arr = [[NSMutableArray alloc] initWithContentsOfFile:finalPath];
return arr;
} else {
return nil;
}
}
Hope it can help you.
[[NSMutableArray alloc] initWithContentsOfFile:prsPath] will load a plist ant initialize an array with it. Does you plist exist at that path already? You might also want to log the prsPath to see if it's correct.
Usually you would first check to see if a plist exists at the path by calling [[NSFileManager defaultManager] fileExistsAtPath:prsPath]. If it does not, you initialize an empty array.
Later you save it by calling [prs writeToFile:prsPath atomically:YES].
Note that you can't initialize NSMutableArrays from plists. Arrays and dictionaries loaded from plists are always immutable. You would have to first load the plist into an NSArray and then initialize an NSMutableArray from that NSArray.
i'm sorry for the obvious question, but is there something i should be careful about when writing data to a file, because my program can read the data it just wrote, while the program is running, but the moment i stop it, the files become empty
tried using NSFileHandle, in order to write data with it, and close the file later, didn't help... currently, i'm using:
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:newArray];
[encodedObject writeToFile:string atomically:YES];
and no matter what i do, i can't get the simplest NSString to stay in the file permanently
what do i do?
Thanks #LetzFlow, but it didn't solve it just yet.
Now, i'm using:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
string = [NSString stringWithFormat:#"%d.rtf",fileName];
NSString *file = [documentsDirectory stringByAppendingPathComponent:string];
//NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:file];
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:newArray];
[encodedObject writeToFile:file atomically:YES];
//[fileHandle writeData:encodedObject];
//[fileHandle closeFile];
NSLog(#"%#",[NSString stringWithContentsOfFile:file encoding:NSStringEncodingConversionAllowLossy error:nil]);
to serialize an array of objects, and it the NSLog shows a valid array. Yet, when I look at the file later, or try to unserialize the array (like this):
NSString *stringX = [NSString stringWithFormat:#"%d.rtf",fileName];
NSData *encodedObjectX = [NSData dataWithContentsOfFile:stringX];
NSArray *newArrayX = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObjectX];
TurnigButton *button = [[newArrayX objectAtIndex:1] objectAtIndex:5];
NSLog(#"%d", button.idNum);
it just prints (null). (when they execute one after the other in a single run, it unserializes just fine)
I appreciate the help.
The question is WHERE do you write your file? Because you are not allowed to write files all over the system in iOS.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
The documents directory is usually a place were you can write files, so you might want to give that a try.
I have a dictionary containing a JSON response and a plist file. I want to update the values in my plist file with the JSON response values. How would I do this?
this is what i did, im working on it now, but im getting there:
JSON to dictionary:
NSString *jsonString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
//NSLog(#"%#",jsonString);
NSArray *result = [jsonString JSONValue];
for(NSDictionary *dictionary in result){
return dictionary; //if you are getting more then one row, do something here
}
Saving the dictionary:
id plist = plistDict;
NSString *errorDesc;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Data.plist"];
NSLog(#"%#",plistPath);
NSData *xmlData;
NSString *error;
xmlData = [NSPropertyListSerialization dataFromPropertyList:plist
format:NSPropertyListXMLFormat_v1_0
errorDescription:&error];
if(xmlData) {
if ([xmlData writeToFile:plistPath atomically:YES]) {
NSLog(#"Data successfully saved.");
}else {
NSLog(#"Did not managed to save NSData.");
}
}
else {
NSLog(#"%#",errorDesc);
[error release];
}
}
if you want to update values, I would say you should open the plist, place it in a dictionary, update the value in the dictionary, and save the dictionary to the plist again.
Hope this helps.
If you are working under Mac OS X 10.7 or iOS 5, there is a Foundation class called NSJSONSerialization that will read/write JSON files. Converting JSON to plist will be as simple as: (Implying you have ARC or GC on)
NSString *infile = #"/tmp/input.json"
NSString *oufile = #"/tmp/output.plist"
[[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:infile]
options:0
error:NULL] writeToFile:oufile
atomically:YES];
However a conversion from plist to JSON will be more troublesome since NSDate and NSData objects cannot appear in JSONs. You may need to check the contents of the file and store the NSData and NSDate in an alternate way (like NSData as Base-64 strings and NSDate as their UNIX times)