Copying JSON response dictionary to plist - objective-c

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)

Related

Writing NSArray into plist

I'm trying to save a NSMutableArray into a pre-existing plist.
When I try:
NSError *errorDesc;
NSPropertyListFormat format;
NSString *plistPath;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
plistPath = [rootPath stringByAppendingPathComponent:#"Array_Label_Generiche.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
NSLog(#"prima volta");
plistPath = [[NSBundle mainBundle] pathForResource:#"Array_Label_Generiche" ofType:#"plist"];
}
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSMutableArray *temp = (NSMutableArray *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %lu", errorDesc, format);
}
contatore = (int)temp.count ;
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
[dictionary setObject:array_copiato forKey:[NSString stringWithFormat: #"%#", [alertView textFieldAtIndex:0].text]];
NSDictionary *dictionary_da_salvare = [[NSDictionary alloc ] initWithDictionary: dictionary];
//AGGIUNGO I DATI CREATI
NSLog(#"TEMP %#",temp);
[temp addObject:dictionary_da_salvare];
BOOL didWriteArray = [temp writeToFile:plistPath atomically:YES];
if (didWriteArray)
{
NSLog(#"Write to .plist file is a SUCCESS!");
}
else
{
NSLog(#"Write to .plist file is a FAILURE!");
}
In this case, output show me that "Write to .plist file is a FAILURE!".
In the Apple Guide, I read that I must serialize data before writing on the plist.
Then I tried to write these lines of code:
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:temp format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if(plistData == nil){
NSLog (#"error writing to file: %#", errorDesc);
}
When I run the application, the output area reads:
error writing to file: Property list invalid for format (property
lists cannot contain objects of type 'CFType') Write to .plist file
is a FAILURE!
I think because the array test is NSMutableArray because I have read in the Apple Guide:
The NSPropertyListSerialization class provides methods that convert
property list objects to and from several serialized formats. Property
list objects include NSData, NSString, NSArray, NSDictionary, NSDate,
and NSNumber objects. These objects are toll-free bridged with their
respective Core Foundation types (CFData, CFString, and so on).

How to write and read data from plist to tableview

Hi I am trying to make bookmarks for my browser.
Title of Page, Url of Page, any Comments related to page.
I tried to save it in plist, but unsuccessful. Can anyone can help me to save these thing to plist and retrive in table view. So, when user tap on title it will open url in UIWebView.
Here is the code I have tried, so far:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"bookmarks.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"bookmarks" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *writeUrl = #"Page URL One";
NSString *writeTitle = #"Page Title One";
NSString *writeComment = #"Page comments";
[data setObject:[NSString stringWithString:writeUrl] forKey:#"url"];
[data setObject:[NSString stringWithString:writeTitle] forKey:#"title"];
[data setObject:[NSString stringWithString:writeComment] forKey:#"comment"];
[data writeToFile: path atomically:YES];
NSMutableDictionary *savedUrl = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *value;
value = [[savedUrl objectForKey:#"url"] stringValue];
NSLog(#"%#", value);
UPDATE: I successfully saved and retrieved data to and from plist. Issue is comming in this line
value = [[savedUrl objectForKey:#"url"] stringValue];
By removing stringValue solve the problem.
value = [savedUrl objectForKey:#"url"];
Now My second issue. I make three items named url, title, comment, types String in plist file.
How can i store different urls. Like
name website: inforains
url: inforains.com
title: Info Rains
comment: good website articles
name website: hitechnology
url: hitechnology.com
title: Hitechnology
comment: hmmm
ans soo on..
how can I store data like this.. so all name website will show on tableview and when user click on anyone, data related to that website will show. I hope i clear my question.
To store multiple records as three items named url, title, comment, types String in plist file
change types from string to dictionary and store data in each dictionary individually for key as 1,2,3 ...
OR
Use three mutable array for each url,title and comment and add object at index 0 at the time of saving it.
and access them when required as nsmutable array.
Change this line
value = [[savedStock objectForKey:#"url"] stringValue];
to
value = [savedUrl objectForKey:#"url"];
because you are saving NSString in dictionary... not NSNumber.
Second issue:
//create mutable array to save all objects
NSMutableArray *objectsArray = [data objectForKey:#"objectsArray"];
if(!objectsArray) {
objectsArray = [[NSMutableArray alloc] init];
}
//create and add dictionary into array
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:#"url1", #"title1", #"comment2",nil] forKeys:[NSArray arrayWithObjects:#"url", #"title", #"comment",nil]];
[objectsArray addObject:dictionary];
[data setObject:objectsArray forKey:#"objectsArray"];
[data writeToFile: path atomically:YES];
// to read data
NSMutableDictionary *savedUrl = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSMutableArray *objectsArraySAved = [savedUrl objectForKey:#"objectsArray"];
for (NSMutableDictionary *dic in objectsArraySAved) {
NSLog(#"URL %#", [dic valueForKey:#"url"]);
}
Are you sure [data writeToFile: path atomically:YES]; works? It returns a BOOL, you should check it.
Are you sure savedURL != nil?
For your new problem, you should put all your dictionaries in a mutable array.
NSMutableArray *bookmarkArray = [[NSMutableArray alloc]init];
[bookmarkArray addObject:data];

cocoa and objective c save, edit and load files

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!

Write NSMutableArray to plist not working

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.

Why is my [dictionary objectForKey:#"TOSAcceptedValue"] null?

I'm writing to and reading from a plist in my document directory. First I write the file out if there is no file found. That seemed to work correctly because at first there was no file there and now there is and double-clicking on the file shows the expected content of a key called TOSAcceptedValue with a value of NO.
But if the file is found, which happened after I ran the above once, I try to read in that same value, I'm getting a null value. Here's the code, it may not be pretty as I've been hacking at it for a while to get it to function.
NSError *error;
NSString *TOSAcceptedStatus ;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog( #"paths is %#", paths);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"AppUsage.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
//first see if file exists. if it doesn't then write it out with a value of NO for Terms of Use Accepted
if (![fileManager fileExistsAtPath: path])
{
NSMutableDictionary *appUsageNo = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//here add element to data file and write data to file
NSString *value = #"NO";
[appUsageNo setObject:#"TOSAcceptedValue" forKey:value];
[appUsageNo writeToFile: path atomically:YES];
[appUsageNo release];
//and set TOSAcceptedStatus to no since we know its a no right now
TOSAcceptedStatus = #"NO";
}
else { //file was found at expected location so let's see if they accepted Terms of Use already
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSLog( #"path is %#", path);
TOSAcceptedStatus = [dictionary objectForKey:#"TOSAcceptedValue"];
//NSLog(#"TOSAcceptedStatus is %#", TOSAcceptedStatus);
NSLog(#"TOSAcceptedStatus is %#", [dictionary objectForKey:#"TOSAcceptedValue"]);
[dictionary release];
}
and here's my Console results
2011-09-09 21:47:23.177 myApp[1027:207] paths is (
"/Users/user1/Library/Application Support/iPhone Simulator/4.3/Applications/34562D85-DBE9-4A4F-A142-JEFC1F4808D1/Documents"
)
2011-09-09 21:47:44.915 myApp[1027:207] path is /Users/user1/Library/Application Support/iPhone Simulator/4.3/Applications/34562D85-DBE9-4A4F-A142-JEFC1F4808D1/Documents/AppUsage.plist
2011-09-09 21:47:50.448 myApp[1027:207] TOSAcceptedStatus is (null)
Any clues why I can't get TOSAcceptedStatus back?
Also, am I allowed to write to and read from a plist after app started?
I think your main problem is that you have the object and key backwards:
[appUsageNo setObject:value forKey:#"TOSAcceptedValue"];