I am trying to save/write an Array to the documents directory, and I am completely stuck. I have checked this code with multiple sources online. I switched from and NSArray to a NSMutableArray and that didn't work. From what I can tell is the file isn't being written, because test is coming back null. Thanks in advance
NSArray *results = [parser objectWithData:data1];
NSMutableArray *array2 = [[NSMutableArray alloc] initWithArray:results];
// Create a dictionary from the JSON string
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"EmployeeData.plist"];
//NSLog(#"the path is %#, the array is %#", path, array2);
/////write to file/////
[array2 writeToFile:path atomically:YES];
NSMutableArray *test = [[NSMutableArray alloc ]initWithContentsOfFile:path];
NSLog(#"the test is %#", test);
** update **
I added these lines of code
BOOL write = [results writeToFile:path atomically:YES];
NSLog(#"did it right? %#", write);
and write is null, what does that mean?
This is one of the many objects in my Array
{
0 = "<null>";
1 = "John Doe";
10 = 512;
11 = "<null>";
12 = 1;
13 = 1;
2 = Doe;
3 = Jon;
4 = "<null>";
5 = johndoe;
6 = "<null>";
7 = "<null>";
8 = "john#doe.com";
9 = "<null>";
Type = 1;
Active = 1;
Depart = "<null>";
Emp = "<null>";
Ext = "<null>";
FirstName = Jim;
Fl = 512;
Name = "John Doe";
Log = jd;
Mobile = "<null>";
Title = "<null>";
}
Do the null values have anything to do with it?
SOLVED!!
I realized that the null values may have been causing some issues, so i changed my query to take care of that and it saved instantly. The above code is 100% correct and it works!
thanks for the help
As per the documentation, writeToFile: only works if your array's contents are limited to a handful of types (NSString, NSData, NSArray, or NSDictionary objects). If you have any other type of object in your array, then it will not write to file correctly (or at all).
Note also that writeToFile: returns a boolean value indicating whether or not the operation succeeded.
If your array contains incompatible types, you will have to look at using something like NSKeyedArchiver to serialize your data instead.
Related
NSString *jsonString = #"{\"eventData\":{\"eventDate\":\"Jun 13, 2012 12:00:00 AM\",\"eventLocation\":{\"latitude\":43.93838383,\"longitude\":-3.46},\"text\":\"hkhkjh\",\"imageData\":\"\",\"imageFormat\":\"JPEG\",\"expirationTime\":1339538400000},\"type\":\"Culture\",\"title\":\"accIDENTE\"}";
NSData *jsonData1 = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *finalDictionary1 = [NSJSONSerialization JSONObjectWithData:jsonData1 options:NSJSONReadingAllowFragments error:nil];
NSLog(#"%#", finalDictionary1);
NSMutableArray *jsonParseArray = [[NSMutableArray alloc] initWithArray:[finalDictionary1 objectForKey:#"latitude"]];
NSDictionary *res = [jsonParseArray objectAtIndex:1];
NSLog(#"%#", res);
When I run this I get a bunch of errors. I want to get the value of latitude.
Your json don't have latitude key. See below.
{
eventData = {
eventDate = "Jun 13, 2012 12:00:00 AM";
eventLocation = {
latitude = "43.93838383";
longitude = "-3.46";
};
expirationTime = 1339538400000;
imageData = "";
imageFormat = JPEG;
text = hkhkjh;
};
title = accIDENTE;
type = Culture;
}
=> New array with empty object.
NSMutableArray *jsonParseArray = [[NSMutableArray alloc] initWithArray:[finalDictionary1 objectForKey:#"latitude"]];
and you try with none exist element.
NSDictionary *res = [jsonParseArray objectAtIndex:1];
See your json: latitude is not an array. And it's child element of eventLocation. Try to get eventLocation as Dictionary first then get latitude via eventLocation.
Hop this helps!
This code will get the latitude from data.
NSString *jsonString = #"{\"eventData\":{\"eventDate\":\"Jun 13, 2012 12:00:00 AM\",\"eventLocation\":{\"latitude\":43.93838383,\"longitude\":-3.46},\"text\":\"hkhkjh\",\"imageData\":\"\",\"imageFormat\":\"JPEG\",\"expirationTime\":1339538400000},\"type\":\"Culture\",\"title\":\"accIDENTE\"}";
NSData *jsonData1 = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *finalDictionary1 = [NSJSONSerialization JSONObjectWithData:jsonData1 options:NSJSONReadingAllowFragments error:nil];
NSLog(#"%#", finalDictionary1);
NSString *latitute = finalDictionary1[#"eventData"][#"eventLocation"][#"latitude"];
NSLog(#"%#", latitute);
Although in a real world example were your JSON might come from a server, you will probably want to add error handling, indexing the data in multiple steps assuring the keys exists and values are of the expected type.
json is a NSMutableDictionary with a key "message". I need to "clean" the data in that key using stringByReplacingOccurrencesOfString
NSLog(#"json: %#", json); outputs this:
json: {
conversationId = 61;
countmessagesinconversation = 2;
message = "Messages exist!";
messagesinconversation = (
{
message = "Hi";
messagecreated = "June 24, 2013 16:16";
messageid = 68;
sentby = Thomas;
sentbyID = 1;
title = "Subject";
},
{
message = "What's up?";
messagecreated = "September 22, 2013 17:00";
messageid = 331;
sentby = Steve;
sentbyID = 2;
title = "Subject";
}
);
success = 1;
}
So, this is what I've come up with, but I'm clearly getting it all wrong.
NSString *newstr = [[NSString alloc]init];
for (newstr in [[[json objectForKey:#"messagesinconversation"]allKeys]copy]){
newstr = [newstr stringByReplacingOccurrencesOfString:#" "
withString:#""];
[json setValue:newstr forKey:#"message"];
}
Could somebody please help me out with this and explain so I understand the concept? I know how to do this with an array but what my problem is (I think) is that I do not fully understand how to access the right key in the dictionary.
Edit: Sorry for not being clear in my question. What happens is that if there are two space characters in the key message then " " shows up when I display it on the screen.
//First get the array of message dictionaries:
NSArray * messages = [json objectForKey:#"messagesinconversation"];
//create new array for new messages
NSMutableArray * newMessages = [NSMutableArray arrayWithCapacity:messages.count];
//then iterate over all messages (they seem to be dictionaries)
for (NSDictionary * dict in messages)
{
//create new mutable dictionary
NSMutableDictionary * replacementDict = [NSMutableDictionary dictionaryWithDictionary:dict];
//get the original text
NSString * msg = [dict objectForKey:#"message"];
//replace it as you see fit
[replacementDict setObject:[msg stringByReplacingOccurrencesOfString:#" " withString:#""] forKey:#"message"];
//store the new dict in new array
[newMessages addObject:replacementDict];
}
//you are done - replace the messages in the original json dict
[json setObject:newMessages forKey:#"messagesinconversation"];
Add your array of dictionary in another mutable array
NSMutableArray *msgArray = [[json objectForKey:#"messagesinconversation"] mutableCopy];
Use for loop for access it.
for (int i = 0 ; i < msgArray.count ; i++)
{
[[[msgArray objectAtindex:i] objectForKey:#"message"] stringByReplacingOccurrencesOfString:#" " withString:#""];
}
[self.mainJSONDic setValue:msgArray forKey:#"messagesinconversation"];
Try this code might helpful in your case:
Now that the requirements are more clear I'll try an answer. I try to use the same names as in your question and suggested in erlier answers.
Make json an NSMUtableDictionary where you declare it. Then go forward:
json = [json mutableCopy]; // creates a mutable dictionary based on json which is immutable as result of the json serialization although declared as mutable.
NSMutableArray *msgArray = [[json objectForKey:#"messagesinconversation"] mutableCopy]; //this fetches the array from the dictinary and creates a mutable copy of it.
[json setValue:newstr forKey:#"messagesinconversation"]; // replace the original immutable with the mutable copy.
for (int i = 0; i < [msgArray count]; i++) {
NSMutableDictionary mutableInnerDict = [[msgArray objectAtIndex:i] mutableCopy]; // fetching the i-th element and replace it by a mutable copy of the dictionary within.
[msgArray replaceObjectAtIndex:i withObject:mutableInnerDict]; // it is now mutable and replaced within the array.
NSString *newString = [[[msgArray objectAtindex:i] objectForKey:#"message"] stringByReplacingOccurrencesOfString:#" " withString:#" "]; // crates a new string with all   removed with blanks.
[mutableInnerDict setValue:newString forKey:#"message"];
}
Regarding the replacement of   with " ", is this really what you want? I am asking because   does not occur in your sample data. Or do you want to remove blanks at all?
Im using foursquare API to get some locations around me, but when the name of that place wasn't in english, the name will be like follows:
name = "\U0645\U0633\U062c\U062f \U0627\U0644\U0633\U064a\U062f\U0629 \U0639\U0627\U0626\U0634\U0629 | Aisha Mosque";
i tried to convert the response to a UTF-8 but nothing changed.
Here is my code:
-(void)setUpLocations{
NSURL *url = [NSURL URLWithString: #"https://api.foursquare...."];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSLog(#"Response: %#",[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"]);
}
And the log result is:
contact = {
};
id = 51712507498ec4e8c5ae9f48;
likes = {
count = 0;
groups = (
);
};
location = {
address = Abdoun;
cc = JO;
city = Amman;
country = Jordan;
distance = 3819;
lat = "31.95406043797281";
lng = "35.88095228186612";
};
name = "\U0645\U0633\U062c\U062f \U0627\U0644\U0633\U064a\U062f\U0629 \U0639\U0627\U0626\U0634\U0629 | Aisha Mosque";
restricted = 1;
stats = {
checkinsCount = 43;
tipCount = 2;
usersCount = 23;
};
verified = 0;
},
Any Suggestions ??
EDIT:
here is how i extract the data from the dictionary:
NSDictionary *dic = [[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"] copy];
namesArray = [[NSArray alloc]initWithArray:[self removeWhiteSpaces:[dic valueForKey:#"name"]]];
-(NSArray *)removeWhiteSpaces:(NSDictionary *)dic{
NSString *str = [NSString stringWithFormat:#"%#",dic];
NSString *str2 = [str stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSString *secondString = [str2 stringByReplacingOccurrencesOfString:#" " withString:#""];
NSString *thirdString = [secondString stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *forthString = [thirdString stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *fifthString = [forthString stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSArray *items = [fifthString componentsSeparatedByString:#","];
return items;
}
And in the UITableView:
cell.textLabel.text = [NSString stringWithFormat:#"Name: %# ",[namesArray objectAtIndex:indexPath.row] ];
Update
After trying #Martin R answer i got the same results:
NSDictionary *dic = [[[[json objectForKey:#"response"]objectForKey:#"groups"]valueForKey:#"items"] copy];
NSString *value =[dic valueForKey:#"name"];
NSLog(#"%#", value);
UILabel *lbl = [[UILabel alloc]initWithFrame:self.view.frame];
lbl.numberOfLines = 0;
lbl.text = [NSString stringWithFormat:#"%#",value];;
[self.view addSubview:lbl];
and here is an image of the result
There is no problem.
NSLog() calls the description method of NSDictionary and NSArray, and that prints all non-ASCII characters as \Unnnn escape sequence.
If you extract the string values from the dictionary and print that you will see
that everything is correct.
Simple example:
NSDictionary *dict = #{ #"currency": #"€" };
NSLog(#"%#", dict);
// Output: { currency = "\U20ac"; }
NSString *value = dict[#"currency"];
NSLog(#"%#", value);
// Output: €
UPDATE: The problem seems to be in your removeWhiteSpaces: method, because
NSString *str = [NSString stringWithFormat:#"%#",dic];
already uses the description method to convert the dictionary to a string,
and the following stringByReplacingOccurrencesOfString calls are a (sorry!) very bad
method to fix that.
You should access the dictionary keys with objectForKey instead, or enumerate
the dictionary with for (NSString *key in dic) { ... } and build the desired
array.
UPDATE 2: From the JSON data (posted in chat discussion) it seem that you just need
NSArray *itemsArray = json[#"response"][#"groups"][0][#"items];
NSArray *namesArray = [itemsArray valueForKey:#"name"];
Note that "groups" is an array with one element.
Try to use this one..
[NSString stringWithUTF8String:]
I am trying to use NsKeyedArchiever to take save Car details which contains model,make,year,color,vin.
The code for this is as follows :
void CarData()
{
Car *myCar = [[Car alloc] init];
myCar.model = [carTempArray objectAtIndex:0];//Temporary array contains value
myCar.make = [carTempArray objectAtIndex:1];
myCar.color = [carTempArray objectAtIndex:2];
myCar.year = [carTempArray objectAtIndex:3];
myCar.vin = [NSNumber numberWithInt:check];
NSString *docspath = [NSHomeDirectory() stringByAppendingPathComponent:#"documents"];
BOOL saved =[NSKeyedArchiver archiveRootObject: myCar toFile:docspath];
NSLog(#"did save state %d",saved);
[myCar release];
[NSKeyedArchiver release];
}
And after that using NSkeyedUnarcheiver as follows :
void ShowData()
{
NSString *docspath = [NSHomeDirectory() stringByAppendingPathComponent:#"documents"];
Car * retrieveCar = [NSKeyedUnarchiver unarchiveObjectWithFile:docspath];
// for(int i=0 ; i<studentList.count;i++)
{
// Car * retrieveCar =[studentList objectAtIndex:0];
NSString * first = retrieveCar.model;
NSString * first1 = retrieveCar.make;
NSString * first2 = retrieveCar.color;
NSString * first3 = retrieveCar.year;
NSLog(#"%#",first );
NSLog(#"%#",first1 );
NSLog(#"%#",first2 );
NSLog(#"%#",first3 );
}
But this only takes one value and uses one value.I want to save the NSKeyedArchiever object in an array so that multiple cars can be a part of it using same code.And Load the same as above.Please rectify the problem .I want to run the code for multiple cars and i am able to perform the following tasks in array of cars as searching a car,deleting a car record and adding a car.
I want to store the same number in an array 100 times. These numbers will change later on, but I want to write an if statement using a counter to populate all 100 slots initially with the value of 0. Is there an easy way to do this?
Something like this, where 'block01' needs to change to 'block02', 'block03' etc.:
int block01 = 0;
NSMutableDictionary* myDict = [[NSMutableDictionary alloc] init];
if(myDict)
{
[myDict setObject:block01 forKey:#"block01stored"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSString *path = [documentPath stringByAppendingPathComponent:#"blocks.save"];
BOOL successfulWrite = [myDict writeToFile: path atomically: YES];
if(successfulWrite == NO)
}
This should help you. It's a loop that will execute 99 times (1 - 100) adding zero as the object for a key formatted to include the current number.
NSMutableDictionary* myDict = [[NSMutableDictionary alloc] init];
for (int i = 1; i <= 100; i ++) {
if(myDict)
{
[myDict setObject:[NSNumber numberWithInt:0] forKey:[NSString stringWithFormat:#"block%.3istored",i]];
}
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
NSString *path = [documentPath stringByAppendingPathComponent:#"blocks.save"];
BOOL successfulWrite = [myDict writeToFile: path atomically: YES];
if(successfulWrite == NO)
EDIT: To get the value for a certain key you can use the following:
int myInt = [[myDict objectForKey:#"block050stored"] intValue];
And if you want to replace the object for a certain key it's as easy as:
[myDict setObject:[NSNumber numberWithInt:1] forKey:#"block020stored"];
Now, the %.3i tells the string to add a number (i) formatted to always be three digits long. (000, 001, 010, 099, 100)
[NSString stringWithFormat:#"block%.3istored",i]
So the above line basically means, create a string with the words "block" and "stored" with a three digit representation of what ever the current value of the int "i" is in between them.
You can create NSNumber (which is an object, but int is not) and then store it into NSMutableDictionary:
NSNumber* num = [NSNumber numberWithInt:0];
for (int i = 1; i<=100; i++) {
[myDict setObject:num forKey:[NSString stringWithFormat:#"block%dstored",i]];
}