Unable to convert UTF-8 text from NSDictionary in Objective-C - objective-c

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:]

Related

Objective C NSDictionary JSON in One line

i'm working on one objective C application where i'm taking JSON data and i need to insert this data(date) inside Dictionary fillDefaultColors. My fillDefaultColors should be in format like this:
self.fillDefaultColors = #{ #"2017/06/18":greenColor,
#"2017/06/19":orangeColor,
#"2017/06/20":greenColor,
...
};
but when i print in console log they are each in separate row and in application i can see colour just for last item from JSON
2017-06-19 15:30:12.310 CalendarTest[1905:364525] {
"2017/06/20" = "greenColor";
}
2017-06-19 15:30:12.311 CalendarTest[1905:364525] {
"2017/06/18" = "orangeColor";
}
So in application i see background for last date in console 2017/06/18
Here is my code
NSError *error = nil;
NSURL *url = [NSURL URLWithString: #"http://..."];
NSData *data = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
if(!error)
{
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
NSMutableArray *array= [json objectForKey:#"horses"];
for(int i=0; i< array.count; i++)
{
NSDictionary *horsedata = [array objectAtIndex:i];
NSString *date = [horsedata objectForKey:#"date"];
NSNumber *averagetemp = [horsedata objectForKey:#"averagetemperature"];
if([averagetemp isEqual:#(28)]) {tempColor = greenColor;} else {
tempColor = orangeColor;
}
self.fillDefaultColors = #{date: tempColor};
NSLog(#"%#", _fillDefaultColors);
}
}
JSON: {"horses":[{"id":1,"name":"Horse","date":"2017/06/17","averagetemperature":28},{"id":1,"name":"Horse","date":"2017/06/18","averagetemperature":25}]}
Thanks
it s because you are allocating a new dictionary in each iteration:
self.fillDefaultColors = #{date: tempColor};
you need to append instead:
NSMutableArray *array= [json objectForKey:#"horses"];
self.fillDefaultColors = [[NSMutableDictionary alloc]init];
for(int i=0; i< array.count; i++)
{
NSDictionary *horsedata = [array objectAtIndex:i];
NSString *date = [horsedata objectForKey:#"date"];
NSNumber *averagetemp = [horsedata objectForKey:#"averagetemperature"];
if([averagetemp isEqual:#(28)]) {tempColor = greenColor;} else {
tempColor = orangeColor;
}
[self.fillDefaultColors setObject:tempColor forKey:date];
NSLog(#"%#", _fillDefaultColors);
}
This is the same solution as in Hussein's answer but with Modern Objective-C Syntax – which has been introduced at least 5 years ago.
NSArray *horses = json[#"horses"];
self.fillDefaultColors = [[NSMutableDictionary alloc] init];
for (NSDictionary *horsedata in horses)
{
NSString *date = horsedata[#"date"];
NSNumber *averagetemp = horsedata[#"averagetemperature"];
self.fillDefaultColors[date] = (averagetemp.integerValue == 28) ? greenColor : orangeColor;
NSLog(#"%#", _fillDefaultColors);
}

How to generate a multi-line UILabel

I have a json call and I parse the results into a UILabel. In my json response I have a 4 Names under Clients.
I am trying to put all the Clients into my UILabel.
Currently I only see the last of the 4 clients from my json response but in my log I can see all 4 clients.
If you see the photo below you see brithouse which is the 4th client in the json call. I would like to view all 4 clients in mu uilabel? Currently I only see the last client.
Thanks
{
"ProfileID":34,
"ProfilePictureID":20,
"Name":"Bilbo Baggins",
"Clients":
[
{
"ClientID":91,
"Name":"Fnurky"
},
{
"ClientID":92,
"Name":"A different client"
},
{
"ClientID":95,
"Name":"Second Community"
},
{
"ClientID":96,
"Name":"Britehouse"
}
]
}
My objective C code
NSDictionary* json1 = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json1 objectForKey:#"Clients"]; //2
NSLog(#"Clients: %#", latestLoans); //3
NSArray *performersArray = [json1 objectForKey:#"Clients"];
for (NSDictionary *performerDic in performersArray) {
NSLog(#"%#", [performerDic objectForKey:#"Name"]);
jsonSummary.text = [NSString stringWithFormat:#"The clients under this user are: %# ",
[performerDic objectForKey:#"Name"]];
NSLOG
2013-05-16 13:03:52.820 com.barloworld.atajo[5137:907] Fnurky
2013-05-16 13:03:52.821 com.barloworld.atajo[5137:907] A different client
2013-05-16 13:03:52.821 com.barloworld.atajo[5137:907] Second Community
2013-05-16 13:03:52.822 com.barloworld.atajo[5137:907] Britehouse
Use this
NSDictionary* json1 = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray* latestLoans = [json1 objectForKey:#"Clients"]; //2
NSArray *performersArray = [json1 objectForKey:#"Clients"];
NSMutableArray *array=[[NSMutableArray alloc]initWithCapacity:3];
for (NSDictionary *performerDic in performersArray) {
[array addObject:[performerDic objectForKey:#"Name"]];
}
NSString *output=[array componentsJoinedByString:#","];
jsonSummary.text = [NSString stringWithFormat:#"The clients under this user are: %# ",
output];
YOu can use this..
before the Loop:
NSString *tempString = #"";
In the Loop:
tempString = [tempString stringByAppendingFormat:#"%#", [performerDic objectForKey:#"Name"]];
After the Loop:
jsonSummary.text = [NSString stringWithFormat:#"The clients under this user are: %#", tempString];
This below of code will only add the last value into the label
jsonSummary.text = [NSString stringWithFormat:#"The clients under this user are: %# ",
[performerDic objectForKey:#"Name"]];
You have to APPEND each client name into string and then display the string value into the label... For appending into the string do,
JsonString =[NSString stringByAppendingFormat: [performerDic objectForKey:#"Name"]];
Now this string will have all Client values, Now
jsonSummary.text =[NSString stringWithFormat : #"YOUR OWN LINES %# " JsonString];

yahoo weather api parsing

How can I parse the wind spped for the following JSON that I have received from the link
http://weather.yahooapis.com/forecastjson?w=2502265. I am getting a garbage value from it but getting the rest of the values correctly. Can anybody let me know how can I get the wind speed out of it?
{"units":{"temperature":"F","speed":"mph","distance":"mi","pressure":"in"},"location":{"location_id":"USCA1116","city":"Sunnyvale","state_abbreviation":"CA","country_abbreviation":"US","elevation":82,"latitude":37.39,"longitude":-122.03},"wind":{"speed":0,"direction":"CALM"},"atmosphere":{"humidity":"86","visibility":"10","pressure":"30.21","rising":"falling"},"url":"http:\/\/weather.yahoo.com\/forecast\/USCA1116.html","logo":"http:\/\/l.yimg.com\/a\/i\/us\/nt\/ma\/ma_nws-we_1.gif","astronomy":{"sunrise":"06:27","sunset":"18:11"},"condition":{"text":"Fair","code":"33","image":"http:\/\/l.yimg.com\/a\/i\/us\/we\/52\/33.gif","temperature":49},"forecast":[{"day":"Today","condition":"PM Showers","high_temperature":"64","low_temperature":"47"},{"day":"Tomorrow","condition":"Partly Cloudy","high_temperature":"62","low_temperature":"45"}]}
NSString *linkForWoeid = [NSString stringWithFormat:#"http://where.yahooapis.com/geocode?location=%#,%#&flags=J&gflags=R&appid=zHgnBS4m",latitude,longitude];
NSURL *woeid = [NSURL URLWithString:linkForWoeid];
NSData *WoeidData = [NSData dataWithContentsOfURL:woeid];
if (WoeidData != NULL)
{
NSError *woeiderr = nil;
//NSLog(#"linkForWoeid:%#woeid:%#woeidData:%#",linkForWoeid,woeid,WoeidData);
NSDictionary *response1=[NSJSONSerialization JSONObjectWithData:WoeidData options:NSJSONReadingMutableContainers error:&woeiderr];
NSDictionary *woeidDict = [[[[response1 objectForKey:#"ResultSet"]objectForKey:#"Results"]objectAtIndex:0]objectForKey:#"woeid"];
NSString *address=[NSString stringWithFormat:#"http://weather.yahooapis.com/forecastjson?w=%#",woeidDict];
NSURL *url=[NSURL URLWithString:address];
NSData *data=[NSData dataWithContentsOfURL:url];
NSError *eqw=nil;
if (data != NULL)
{
NSDictionary *response=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&eqw];
//NSLog(#"response:%#",response);
NSString *highTempDict = [[[response objectForKey:#"forecast"]objectAtIndex:0] objectForKey:#"high_temperature"];
NSString *temp = [highTempDict stringByAppendingFormat:#" 'F"];
NSString *windSpeed = [[response objectForKey:#"wind"] objectForKey:#"speed"];
NSLog(#"wind :%#",windSpeed);
if (windSpeed == 0)
{
NSLog(#"insideif");
windSpeed = #"0";
}
NSString *imageView = [[response objectForKey:#"condition"]objectForKey:#"image" ];
Hi Rasi Please use NSNumber instead of NSString here
NSNumber *windSpeed = [[response objectForKey:#"wind"] objectForKey:#"speed"];
As in JSON it's coming as integer value (without quotes) so it is not a NSString but NSNumber
And you can get it's string value as [windSpeed stringValue];

Extracting number from NSString

I have an NSString which when logged gives me an answer like this one:
Response: oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z
The two numbers change every single time.
Is there a way to extract the two numbers and create two strings with one of each??
Like:
NSString *key = #"9tmqsojggieln6z";
//copy the string in a new string variable
NSMutableString *auth_token = [NSMutableString stringWithString:response];
NSRange match = [auth_token rangeOfString: #"&oauth_token="];
[auth_token deleteCharactersInRange: NSMakeRange(0, match.location+13)];
//auth_token will now have the auth token string
NSMutableString *auth_token_secret = [NSMutableString stringWithString:response];
NSRange range1 = [auth_token_secret rangeOfString:[NSString stringWithFormat:#"&oauth_token=%#", auth_token]];
[auth_token_secret deleteCharactersInRange:range1];
NSRange range2 = [auth_token_secret rangeOfString:#"oauth_token_secret="];
[auth_token_secret deleteCharactersInRange: range2];
//auth_token_secret will have the required secret string.
I had the same problem. As response I get the ids of objects sometimes as string sometimes as numbers. Then I wrote a category for NSDictionary which has the following method:
- (NSString *)stringFromStringOrNumberForKey:(NSString *)key
{
id secret = [self objectForKey:key];
if ([secret isKindOfClass:[NSNumber class]]) {
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
secret = [numberFormatter stringFromNumber:secret];
}
return secret;
}
I would try the following:
NSString *_response = #"oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z";
NSMutableDictionary *_dictionary = [[NSMutableDictionary alloc] init];
NSArray *_parameters = [_response componentsSeparatedByString:#"&"];
for (NSString *_oneParameter in _parameters) {
NSArray *_keyAndValue = [_oneParameter componentsSeparatedByString:#"="];
[_dictionary setValue:[_keyAndValue lastObject] forKey:[_keyAndValue objectAtIndex:0]];
}
// reading the values
NSLog(#"token_secret : %#", [_dictionary valueForKey:#"oauth_token_secret"]);
NSLog(#"token : %#", [_dictionary valueForKey:#"oauth_token"]);

JSON text and variable count

I am reading like this...
NSString *fileContent = [[NSString alloc] initWithContentsOfFile:path];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *data = (NSDictionary *) [parser objectWithString:fileContent error:nil];
// getting the data from inside of "menu"
NSString *message = (NSString *) [data objectForKey:#"message"];
NSString *name = (NSString *) [data objectForKey:#"name"];
NSArray *messagearray = [data objectForKey:#"message"];
NSArray *namearray = [data objectForKey:#"name"];
NSDictionary* Dictionary = [NSDictionary dictionaryWithObjects:message forKeys:name];
for (NSString* Key in [Dictionary allKeys]){
NSLog(#"%# %#",Key,[Dictionary objectForKey:Key]);
}
...this JSON file...
{"message":["Untitled1a","Untitled2a","Untitled3a"],"name": ["Untitled1b","Untitled2b","Untitled3b"]}
...this is the result...
Untitled3b Untitled3a
2012-05-12 11:31:17.983 Quick Homework[721:f803] Untitled1b Untitled1a
2012-05-12 11:31:17.983 Quick Homework[721:f803] Untitled2b Untitled2a
...but for each pair (Untitled 1b 2b) I would like to alloc two UITextFields, witch display the correspondent text...
I tried using this method:
for (NSString *string in messagearray){
}do{
NSLog(#"happt = %i", b);
b++;
}
while(b == b);
//While loop
while (b == b ) {
NSLog(#"x = %i", b);
b++;
}
}
I would like to count the objects in the array in order to repeat an alloc code for UITextField that number of times, and display the text accordingly, but I am not able. Please help!!
Why can't you use -count?
b = [messagearray count]
To directly answer your question:
b = 0;
for (id item in messagearray)
b++;