Can we get user zip code using facebook sdk? - iphone

I am using facebook sdk 3.0
At facebook i have added users full address as
Address- 1, Infinite loop
city/town - Cupertino, CA
UPDATE
As per the answer I tried to use FBGraphLocation protocol like this
NSDictionary<FBGraphUser> *user
id<FBGraphPlace> objPlace = user.location;
id<FBGraphLocation> objLocation = objPlace.location;
NSLog(#"place.location : %# location.street : %#",objPlace.location,objLocation.street);
It is giving (null) for both. also I am getting objLocation object as (null)
In facebook sdk response, I am getting location as only this
location = {
id = 123456789123456;
name = "Cupertino, California";
}
This is not the enough information from where i can get the zipcode of the use.
If facebook does not allow to provide zip code information then any way to get zipcode from only "Cupertino, California" information ?
I have used this url
http://maps.googleapis.com/maps/api/geocode/json?address=Cupertino,%20California&sensor=true
which give me result as
{
"long_name" = Cupertino;
"short_name" = Cupertino;
types = (
locality,
political
);
},
{
"long_name" = "Santa Clara";
"short_name" = "Santa Clara";
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = California;
"short_name" = CA;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = "United States";
"short_name" = US;
types = (
country,
political
);
}
If I statically put that address into the URL as
http://maps.googleapis.com/maps/api/geocode/json?address=1%20Infinite%20Loop,%20Cupertino,%20CA&sensor=true
Then It gives me Zip code also.
{
"long_name" = 1;
"short_name" = 1;
types = (
"street_number"
);
},
{
"long_name" = "Apple Inc.";
"short_name" = "Apple Inc.";
types = (
establishment
);
},
{
"long_name" = "Infinite Loop";
"short_name" = "Infinite Loop";
types = (
route
);
},
{
"long_name" = Cupertino;
"short_name" = Cupertino;
types = (
locality,
political
);
},
{
"long_name" = "Santa Clara";
"short_name" = "Santa Clara";
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = California;
"short_name" = CA;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = "United States";
"short_name" = US;
types = (
country,
political
);
},
{
"long_name" = 95014;
"short_name" = 95014;
types = (
"postal_code"
);
}
But from the Facebook sdk, I am only getting the City/Town (as stated above), added in contact Information at Facebook.com
How can I do this?

After digging into the SDK I found out, that you can access a user's zipcode and street using the FBGraphLocation API, which is part of the FBGraph API.
To get a FBGraphLocation you'll acess the location property of a FBGraphUser
/*!
#property
#abstract Typed access to the user's current city.
*/
#property (retain, nonatomic) id<FBGraphLocation> location;
The FBGraphLocation API has those properties available:
/*!
#property
#abstract Typed access to a location's street.
*/
#property (retain, nonatomic) NSString *street;
/*!
#property
#abstract Typed access to a location's zip code.
*/
#property (retain, nonatomic) NSString *zip;
That's what you need, right?

Finally I used google API to get the latitude and longitude from the address I get from the facebook and using those coordinates I find the zip code.
- (CLLocation *) getGeoCoordinatesUsingAddress: (NSString *) aStrAddres
{
NSString *esc_addr = [aStrAddres stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat:BaseURLForLocation, esc_addr];
NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:req] encoding:NSUTF8StringEncoding error:NULL];
NSDictionary *googleResponse =
[NSJSONSerialization JSONObjectWithData: [result dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: nil];
NSDictionary *resultsDict = [googleResponse valueForKey:#"results"];
NSDictionary *geometryDict = [resultsDict valueForKey:#"geometry"];
NSDictionary *locationDict = [geometryDict valueForKey:#"location"];
NSArray *latArray = [locationDict valueForKey: #"lat"]; NSString *latString = [latArray lastObject];
NSArray *lngArray = [locationDict valueForKey: #"lng"]; NSString *lngString = [lngArray lastObject];
CLLocation *locationFound = [[CLLocation alloc] initWithLatitude:[latString doubleValue] longitude:[lngString doubleValue]];
NSLog(#"%s lat: %f\tlon:%f ",__FUNCTION__, [latString doubleValue], [lngString doubleValue]);
return locationFound;
}
Then I used CLGeocoder class
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
for(CLPlacemark *aPlacemark in placemarks){
NSString *strZipCode = [aPlacemark.addressDictionary objectForKey:(NSString *)kABPersonAddressZIPKey];
}
}];
Hope this help..

Related

Filtering an NSDictionary within a dictionary with particular text

I am getting a web service repsonse that is an array of dictionary. Each dictionary has objects whose values itself is another dictionary.I need to implement the search within this response,like if i enter "technology" and go for search, I should get those dictionary from the array that has "technology anywhere within that dictionary", Is there a solution to sort out
{
key1 = {
0 = {
"id" = 608;
"b" = "Apple-Iphone";
};
1 = {
"id" = 609;
"b" = "Iphone";
};
2 = {
"id" = 610;
"b" = "Show Text";
};
};
key2 = "Technology resources";
"key3" = {
0 = {
"id" = 1608;
"b" = "I love reading";
};
1 = {
"id" = 1609;
"b" = "I prefer iphone to others";
};
2 = {
"id" = 1610;
"b" = "Mobile technology is great.I am happy to a be developer";
};
};
"key4" = "Mobile technology is the fun";
}
This is First Method
NSMutableDictionary *dict;
NSArray *allKeys = [dict allKeys];
for (NSString *key in allKeys)
{
NSDictionary *innerDict = [dict objectForKey:key];
NSArray *allInnerKeys = [innerDict allKeys];
for (NSString *innerKey in allInnerKeys)
{
NSDictionary *mostInnerDict = [dict objectForKey:innerKey];
NSString *b = [mostInnerDict objectForKey:b];
NSString *search = #"Technology";
NSString *sub = [b substringFromIndex:NSMaxRange([b rangeOfString:search])];
if(sub)
{
// ADD mostInnerDict Object to your Results Array
}
}
}
Or You can Try The Simpler Method
Get Response in NSDATA
Covert NSDATA To NSString
and search in NSSTRING for Substring

Re-arrange NSArray and NSDictionary entries

I have array with nsdictionary objects, for ex.:
({"someKey" = "title";
"name" = "someName";
},
{"someKey" = "title";
"name" = "anotherName";
}
{"someKey" = "newTitle";
"name" = "someName";
}
)
Please, help me to sort it in this format:
({"someKey" = "title";
"names": (
{"name" = "someName"},
{"name" = "anotherName"}
)
},
{"someKey" = "newTitle";
"names": (
{"name" = "someName"}
)
}
)
Thanks..
As far as i understand from your question you want to pick individual objects into one single dictionary object..
NSArray *yourArray=.... /* array which contains this data: ({"someKey" = "title";
"name" = "someName";
},
{"someKey" = "title";
"name" = "anotherName";
}
)*/
NSMutableDictionary *newDictionary=[[NSMutableDictionary alloc]init];
for(int i=0;i<[yourArray count];i++){
[newDictionary setObject:[yourArray objectAtIndex:i] forKey:#"names"];
}
({"someKey" = "title";
"name" = "someName";
},
{"someKey" = "title";
"name" = "anotherName";
}
)
Assuming above is equivalent to
NSArray *array=[NSArray arrayWithObjects:dictionary1,dictionary2,nil];
then to achieve below result
(
{
"someKey" = "title";
"names": (
{"name" = "someName"},
{"name" = "anotherName"}
)
}
)
We have this :
//Get name array
NSMutableArray *names=[NSMutableArray array];
for(int i=0;i<[array count];i++)
{
NSDictionary *dictionary=[array objectAtIndex:i];
[names addObject:[dictionary valueForKey:#"name"];
}
NSDictionary *newDictionary=[NSDictionary dictionaryWithOjbectsAndKeys:#"someKey",#"title",names,#"names",nil];
//Your final result is an array with one object ( A Dictionary )
NSArray *finalArray=[NSArray arrayWithObjects: newDictionary,nil];
You just need to traverse the current structure and build a new dictionary with the title as the unique key:
NSEnumerator* arrayEnumerator = [myArray objectEnumerator];
NSDictionary* = dictFromArray;
NSMutableArray* titleArray = [[NSMutableArray alloc] init];
NSMutableDictionary* titleDict = [[NSMutableDictionary alloc] init];
while(dictFromArray = [arrayEnumerator nextObject])
{
currentTitle = [dictFromArray objectForKey:#"someKey"];
currentName = [dictFromArray objectForKey:#"name"];
if([titles containsObject:currentTitle)
{
NSMutableDictionary namesArray = [titleDict objectForKey:currentTitle];
[namesArray addObject:currentName];
}
else
{
[titles addObject:currentTitle];
[titleDict addObject:[NSMutableArray arrayWithObject:currentName] forKey:currentTitle];
}
}
This should give you a dictionary that looks like:
{
title =
(
someName,
anotherName
);
newTitle =
(
someName
)
}
To get the exact structure you have above, I think this should work:
NSArray* titleKeys = [titleDict allKeys];
NSEnumerator* keyEnumerator = [titleKeys objectEnumerator];
NSMutableArray* finalArray = [[NSMutableArray alloc] init];
NSString* key;
while (key = [keyEnumerator nextObject])
{
[finalArray addObject: [NSDictionary
dictionaryWithObjects:(key, [dictArray objectForKey:key])
forKeys:(#"someKey", #"names")]];
}

CLGeocoder reverseGeocodeLocation not able to product consisent result

I am not able to get same result from CLGeocoder reverseGeocodeLocation for two different coordinate system.
for eg.
CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:37.785834 longitude:-122.406417]; // coordinate for apple head quater
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:tempLocation completionHandler:
^(NSArray* placemarks, NSError* error){
if ([placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#" %#",placemark.addressDictionary);
}
}];
output :
City = "San Francisco";
Country = "United States";
CountryCode = US;
FormattedAddressLines = (
"Apple Store, San Francisco",
"1 Stockton St",
"San Francisco, CA 94108-5805",
"United States"
);
Name = "Apple Store, San Francisco";
PostCodeExtension = 5805;
State = California;
Street = "1 Stockton St";
SubAdministrativeArea = "San Francisco";
SubLocality = "Union Square";
SubThoroughfare = 1;
Thoroughfare = "Stockton St";
ZIP = 94108;
But when I use
CLLocation tempLocation = [[CLLocation alloc] initWithLatitude:27.672654 longitude:85.313744];
///CLLocation *tempLocation = [[CLLocation alloc] initWithLatitude:37.785834 longitude:-122.406417];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:tempLocation completionHandler:
^(NSArray placemarks, NSError* error) {
if ([placemarks count] > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#" %#",placemark.addressDictionary);
}
}];
and the output is
{
Country = Nepal;
CountryCode = NP;
FormattedAddressLines = ( "Pulchowk Road", Nepal );
Name = "Pulchowk Road";
State = Bagmati;
Street = "Pulchowk Road";
Thoroughfare = "Pulchowk Road";
}
The question is why i am not getting all of the information. For eg City , ZIP .. are missing. How should i handle this issue in program.
Geolocation is always using the best available information. Most likely for Nepal the mapping companies with whom Apple or its service provider contracted did not provide the information you are missing. This is more a contractual / service quality issue and I don't think there is anything you can do with it. Except trying to optimize your application to provide the best possible user experience even if it has only incomplete data.

How to get values from unknown key in NSDictionary iphone?

I have one more big problem while parse the values from Webservice response. I dont know the key for the values in the webservice response. For example,
class = (
{
"ObjectiveC" =
(
{
"brief_desc" = "ObjectiveC";
date = "2008-02-27";
"event_status" = Attended;
},
{
"brief_desc" = "ObjectiveC";
date = "2008-03-05";
"event_status" = Attended;
},
{
"brief_desc" = "ObjectiveC";
date = "2008-03-12";
"event_status" = Missed;
},
);
},
{
"Java" = (
{
"brief_desc" = "Java";
date = "2008-02-27";
"event_status" = Attended;
},
{
"brief_desc" = "Java";
date = "2008-03-05";
"event_status" = Attended;
},
{
"brief_desc" = "Java";
date = "2008-03-12";
"event_status" = Missed;
},
);
}
);
In this response even we dont know the keys "ObjectiveC" and "Java". The keys("ObjectiveC and Java") should be change in every response retured. How to get values of key (Unknown key)? How can i parse this response and get the values?
I would enumerate through the keys to get the value. Here is an example of enumeration in objective-c.
NSEnumerator *enumerator = [myDictionary keyEnumerator];
id key;
while ((key = [enumerator nextObject])) {
//assuming value will be string
NSString *valueForKey = [myDictionary valueForKey:key];
//assuming value is another dictionary
NSDictionary *subDictionary = [myDictionary objectForKey:key];
}
And if you don't know the keys of the sub dictionaries, you can enumerate through those as well.
NSDictionary has - (NSArray *)allKeys and - (NSArray *)allValues. One of those might help
NSDictionary * lessonDict = [[NSDictionary alloc] initWithObjectsAndKeys:#"Key", #"Value", #"Key 2", #"Value 2", nil];
NSArray *values = [lessonDict allValues];
NSArray *keys = [lessonDict allKeys];
NSLog(#"Keys: %#",keys);
NSLog(#"Values: %#",values);

Invalid touchJSON string

I get an invalid JSON string, which contains ; ( characters. Any guess what is going on?
My Code:
-(void)getJSONFeed {
// Create the URL & Request
NSURL *feedURL = [NSURL URLWithString:
#"http://maps.googleapis.com/maps/api/geocode/json? address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true"];
NSURLRequest *request = [NSURLRequest requestWithURL:feedURL];
// Example connection only. Add Timeouts, cachingPolicy in production
[NSURLConnection connectionWithRequest:request delegate:self ];
// init the jsonData Property
jsonData = [[NSMutableData data] retain];
}
// NSURLConnection Delegate Methods. You would want to include more for error handling //
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSMutableData *)data {
NSLog(#"Recieving Data...");
// Append the incomming data as it is received
[jsonData appendData:data];
NSLog(#"%#",jsonData);
}
-(NSDictionary *)parseJSON:(NSMutableData *)data {
NSLog(#"Parsing JSON");
NSError *error = nil;
NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:data error:&error];
return dictionary;
}
// Parse JSON results with TouchJSON. It converts it into a dictionary.
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Fininshed Loading...");
NSDictionary * feedDictionary = [self parseJSON:jsonData];
NSLog(#"JSON as NSDictionary: %#", feedDictionary);
}
{
results = (
{
"address_components" = (
{
"long_name" = 1600;
"short_name" = 1600;
types = (
"street_number"
);
},
{
"long_name" = "Amphitheatre Pkwy";
"short_name" = "Amphitheatre Pkwy";
types = (
route
);
},
{
"long_name" = "Mountain View";
"short_name" = "Mountain View";
types = (
locality,
political
);
},
{
"long_name" = "San Jose";
"short_name" = "San Jose";
types = (
"administrative_area_level_3",
political
);
},
{
"long_name" = "Santa Clara";
"short_name" = "Santa Clara";
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = California;
"short_name" = CA;
types = (
"administrative_area_level_1",
political
);
},
{
"long_name" = "United States";
"short_name" = US;
types = (
country,
political
);
},
{
"long_name" = 94043;
"short_name" = 94043;
types = (
"postal_code"
);
}
);
"formatted_address" = "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA";
geometry = {
location = {
lat = "37.422782";
lng = "-122.085099";
};
"location_type" = ROOFTOP;
viewport = {
northeast = {
lat = "37.4259296";
lng = "-122.0819514";
};
southwest = {
lat = "37.4196344";
lng = "-122.0882466";
};
};
};
types = (
"street_address"
);
}
);
status = OK;
}
UPDATE:
Somehow it interprets it as a Property list. The format seems to be similar to the original NeXTSTEP format with = ;
I'm not 100% sure what the question is. You do a valid HTTP connection, which makes a meaningful request from Google (if you delete the six spaces in the middle that are almost certainly a result of the code copy and paste to here). You accumulate the result. In the given code you appear to leak the object jsonData, but I assume that's irrelevant to the question.
You use the CJSONDeserializer object which I've not heard of but seems to be commonly mentioned on Google so is probably trustworthy. It returns a valid NSDictionary. You print the dictionary and it has the correct results in it.
Is the confusion just that when you print the dictionary to the console, it doesn't look identical to the JSON you received? If so then that's because it no longer has any concept that it came from JSON and Cocoa predates the JSON standard and hence doesn't use it for logging.
In any case, feedDictionary is a valid dictionary. The following:
NSLog(#"%#", [feedDictionary objectForKey:#"status"]);
Would print the string 'OK'. This:
NSArray *addressComponents = [feedDictionary objectForKey:#"address_components"];
for(NSDictionary *component in addressComponents)
{
NSLog(#"%#", [component objectForKey:#"long_name"]);
}
Would print the strings '1600', 'Amphitheatre Pkwy', 'Mountain View', 'San Jose', 'Santa Clara', 'California', 'United States', '94043' in that order.
If you want to print the raw JSON to the console, you probably want something like this (assuming the result comes back as UTF8):
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Fininshed Loading...");
NSString *feedString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"JSON was: %#", feedString);
[feedString release];
/*NSDictionary * feedDictionary = [self parseJSON:jsonData];
NSLog(#"JSON as NSDictionary: %#", feedDictionary); */
}
Though then you'll still need to parse it to a dictionary to get meaningful results from it.