yahoo weather api parsing - objective-c

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

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 convert NSData which contains a line break to a NSString

The following code works perfectly to convert the NSData that I got from a URL/JSON file to a NSString, EXCEPTION MADE by the cases that data contains line breaks!
What's wrong with my code?
My Code:
NSError *errorColetar = nil;
NSURL *aColetarUrl = [[NSURL alloc]initWithString:#"http://marcosdegni.com.br/petsistema/teste/aColetar3.php"];
NSString *aColetarString = [NSString stringWithContentsOfURL:aColetarUrl encoding:NSUTF8StringEncoding error:&errorColetar];
NSLog(#"NSString: %#", aColetarString);
if (!errorColetar) {
NSData *aColetarData = [aColetarString dataUsingEncoding:NSUTF8StringEncoding];
self.arrayAColetar = [NSJSONSerialization JSONObjectWithData:aColetarData options:kNilOptions error:nil];
}
NSLog(#"arrayAColetar %#", self.arrayAColetar);
Log Results:
**NSString**: [{"id_atendimento":"2","observacoes":"ABC-Enter-->
DEF-Enter-->
GFH-END"},{"id_atendimento":"1","observacoes":"123Enter-->
345Enter-->
678End"}]
**arrayAColetar** (null)
As you can see my bottom line is an empty array :(
Thanks in advance!
By checking the error message hidden under 'error:nil' I found a "Unescaped control character around character" issue and implemented the code below from Unescaped control characters in NSJSONSerialization
and got a new 'cleaned' string.
- (NSString *)stringByRemovingControlCharacters: (NSString *)inputString {
NSCharacterSet *controlChars = [NSCharacterSet controlCharacterSet];
NSRange range = [inputString rangeOfCharacterFromSet:controlChars];
if (range.location != NSNotFound) {
NSMutableString *mutable = [NSMutableString stringWithString:inputString];
while (range.location != NSNotFound) {
[mutable deleteCharactersInRange:range];
range = [mutable rangeOfCharacterFromSet:controlChars];
}
return mutable;
}
return inputString;
}

Unable to convert UTF-8 text from NSDictionary in 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:]

Blob to image conversion

I am fetching result by fire a transaction but by the transaction one result is coming as blob attributes, that is image, I want to change that blob attribute to image
I wrote code for that "icon" is the key for fetch the image from transaction,
so please help me check this,
image is printing nil,
why?
NSString *inputString = [[[self formModel] attributeAsString:#"icon"] description];
NSLog(#"icon is %#",[[self formModel] attributeAsString:#"icon"]);
NSLog(#"inputstring is %#",inputString);
//NSImage *image = [NSUnarchiver unarchiveObjectWithData:[[self formModel] attributeAsString:#"icon"]];
//NSLog(#"image is %#",image);
NSArray *words = [inputString componentsSeparatedByString:#" "];
NSLog(#"words is %#",words);
NSArray *sizes = [words valueForKey:#"length"];
int sizeOfBytes = 0;
for (NSNumber *size in sizes) {
sizeOfBytes += [size intValue]/2;
}
int bytes[sizeOfBytes];
int counts = 0;
for (NSString *word in words) {
// convert each word from string to int
NSMutableString *ostr = [NSMutableString stringWithCapacity:[word length]];
while ([word length] > 0) {
[ostr appendFormat:#"%#", [word substringFromIndex:[word length] - 2]];
word = [word substringToIndex:[word length] - 2];
}
NSScanner *scaner = [NSScanner scannerWithString:ostr];
unsigned int val;
[scaner scanHexInt:&val];
bytes[counts] = val;
counts++;
}
// get NSData form c array
NSData *data = [NSData dataWithBytes:bytes length:sizeOfBytes];
NSLog(#"My NSDATA %#",data);
NSImage *Image = [[NSImage alloc] initWithData:data];
Never use the output of description to do processing. There is no guarantee of its format. What format is your original "blob" in and how was it generated? Your code suggests it might be an NSData or it might be an NSKeyArchiver. Both of these easily convert to NSData. You never need to do this by hand by converting to a string.

Cryptic SQLite console output in Objective-C

When running my program to query the iPod library of my iPhone, I get the following output in the console:
CPSqliteStatementPerform: attempt to write a readonly database for UPDATE ddd.ext_container SET orig_date_modified = (SELECT date_modified FROM container WHERE pid=container_pid) WHERE orig_date_modified=0
I have disabled everything that outputs to the console so it isn't as if I am having an error with NSLog. What is going on here and how can I fix it. I'll include the overall class source code that I am calling, along with the class that does the work (sorry for posting it all:
+(NSMutableDictionary *) makeQuery {
MPMediaQuery *query = [[MPMediaQuery alloc] init]; //query iPod library
NSString *facebookIDKey = #"Facebook ID";
NSString *genericFacebookID = #"1234567890";
NSMutableDictionary *organizedSongData = [NSMutableDictionary dictionaryWithObject:genericFacebookID forKey:facebookIDKey];
NSArray *allSongs = [query collections];
//only add those songs which have not
//been played since last login
for (MPMediaItem *recent in allSongs) {
NSDate *lastPlayed = [recent valueForProperty:MPMediaItemPropertyLastPlayedDate];
int songCounter = 1;
BOOL uploadInfo = [[PlayedSinceLastLogin alloc] initWithLastPlayedDateOfSong:lastPlayed];
if (uploadInfo == YES) {
//adds songs into
[organizedSongData addEntriesFromDictionary: [MakeDicForSongInfo initWithMPMediaItem:recent andSongNumber:songCounter]];
songCounter++;
}
}
return organizedSongData;
}
Here is the actual brunt of the work, done in the MakeDicForSongInfo:
+(NSDictionary *) initWithMPMediaItem:(MPMediaItem *) song andSongNumber: (int)songCount{
//Create & initialize NSStrings for keys
//Create NSArray to hold keys
NSString *songKey = [NSString stringWithFormat: #"%i Song Title", songCount];
NSString *albumKey = [NSString stringWithFormat: #"%i Album", songCount];
NSString *artistKey = [NSString stringWithFormat: #"%i Artist", songCount];
NSString *artistIDKey = [NSString stringWithFormat: #"%i Artist Persistent ID", songCount];
NSString *lastPlayedKey = [NSString stringWithFormat: #"%i Late Played Date", songCount];
NSString *genreKey = [NSString stringWithFormat: #"%i Genre", songCount];
NSString *ratingKey = [NSString stringWithFormat: #"%i User Rating", songCount];
NSString *playCountKey = [NSString stringWithFormat: #"%i Play Count", songCount];
NSArray *propertyKeys = [[NSArray alloc] initWithObjects:songKey, albumKey, artistKey, artistIDKey,
lastPlayedKey, genreKey, ratingKey, playCountKey, nil];
//Create & initialize NSStrings to hold song property information
//Create NSArray to hold the values
NSString *songTitle = [song valueForProperty:MPMediaItemPropertyTitle];
NSString *albumName = [song valueForProperty:MPMediaItemPropertyAlbumTitle];
NSString *artistName = [song valueForProperty:MPMediaItemPropertyArtist];
NSString *artistID = [song valueForProperty:MPMediaItemPropertyArtistPersistentID];
NSString *lastPlayed = [song valueForProperty:MPMediaItemPropertyLastPlayedDate];
NSString *genre = [song valueForProperty:MPMediaItemPropertyGenre];
NSString *userRating = [song valueForProperty:MPMediaItemPropertyRating];
NSString *playCount = [song valueForProperty:MPMediaItemPropertyPlayCount];
NSArray *propertyValues = [[NSArray alloc] initWithObjects:songTitle, albumName, artistName, artistID,
lastPlayed, genre, userRating, playCount, nil];
//Create NSDictionary to store information, initializing it with
//above data, then returning the resulting dictionary
NSDictionary *songInfo = [[NSDictionary alloc] initWithObjects:propertyValues forKeys:propertyKeys];
return songInfo;
}
Could it be something in accessing all that Media information that spooks the iPhone?
Apparently this is a bug in iOS 4.3 and is addressed in this devforum at Apple:
https://devforums.apple.com/message/428584#428584