Extracting Require information from google map place api in IOS - ios

I am working on GPS app in which i need to determine location based on longitude and Latitude of a place.I am able to determine the longitude and latitude and also location but i am getting the result of the google maps api call in json format in which there is a lot of data along with city name.
I have done like this.(I am using simulator so i have passed fixed latitude and longitude)
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017];
NSError* error;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString] encoding:NSASCIIStringEncoding error:&error];
locationString = [locationString stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSLog(#"%#",locationString );
The output string i am getting is
015-04-16 10:38:45.056 demolocationapp[690:12005] {
results : [
{
address_components : [
{
long_name : Rauni Kalan Link Road,
short_name : Rauni Kalan Link Rd,
types : [ route ]
},
{
**long_name : Rauni Kalan,
short_name : Rauni Kalan,
types : [ locality, political]**
},
{
long_name : Rupnagar,
short_name : Rupnagar,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
},
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
}
],
formatted_address : Rauni Kalan Link Road, Rauni Kalan, Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.8209903,
lng : 76.4550081
},
southwest : {
lat : 30.8178417,
lng : 76.44540219999999
}
},
location : {
lat : 30.8186057,
lng : 76.4507395
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8209903,
lng : 76.4550081
},
southwest : {
lat : 30.8178417,
lng : 76.44540219999999
}
}
},
place_id : ChIJc8IoHwICEDkR38Ie5TOeGu0,
types : [ route ]
},
{
address_components : [
{
long_name : Rauni Kalan,
short_name : Rauni Kalan,
types : [ locality, political ]
},
{
long_name : Rupnagar,
short_name : Rupnagar,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
},
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
}
],
formatted_address : Rauni Kalan, Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.8219531,
lng : 76.4462614
},
southwest : {
lat : 30.81705139999999,
lng : 76.4414979
}
},
location : {
lat : 30.8192965,
lng : 76.44401660000001
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8219531,
lng : 76.4462614
},
southwest : {
lat : 30.81705139999999,
lng : 76.4414979
}
}
},
place_id : ChIJ_f1PWh0CEDkRKlzFwhc62zo,
types : [ locality, political ]
},
{
address_components : [
{
long_name : 140102,
short_name : 140102,
types : [ postal_code ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Punjab 140102, India,
geometry : {
bounds : {
northeast : {
lat : 30.869706,
lng : 76.47508049999999
},
southwest : {
lat : 30.7970006,
lng : 76.3335855
}
},
location : {
lat : 30.8288892,
lng : 76.4215988
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.869706,
lng : 76.47508049999999
},
southwest : {
lat : 30.7970006,
lng : 76.3335855
}
}
},
place_id : ChIJHX2_rA0BEDkR_QslHcc_M0g,
types : [ postal_code ]
},
{
address_components : [
{
long_name : Fatehgarh Sahib,
short_name : Fatehgarh Sahib,
types : [ administrative_area_level_2, political ]
},
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Fatehgarh Sahib, Punjab, India,
geometry : {
bounds : {
northeast : {
lat : 30.8779699,
lng : 76.63427999999999
},
southwest : {
lat : 30.4275501,
lng : 76.0761799
}
},
location : {
lat : 30.6810924,
lng : 76.4100267
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 30.8779699,
lng : 76.63427999999999
},
southwest : {
lat : 30.4275501,
lng : 76.0761799
}
}
},
place_id : ChIJqf6CHWocEDkR4EljDGd5be8,
types : [ administrative_area_level_2, political ]
},
{
address_components : [
{
long_name : Punjab,
short_name : PB,
types : [ administrative_area_level_1, political ]
},
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : Punjab, India,
geometry : {
bounds : {
northeast : {
lat : 32.4981352,
lng : 76.92175809999999
},
southwest : {
lat : 29.537147,
lng : 73.8708879
}
},
location : {
lat : 31.1471305,
lng : 75.34121789999999
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 32.4981352,
lng : 76.92175809999999
},
southwest : {
lat : 29.537147,
lng : 73.8708879
}
}
},
place_id : ChIJVXOeVqpkGTkRYYijAzEmvY8,
types : [ administrative_area_level_1, political ]
},
{
address_components : [
{
long_name : India,
short_name : IN,
types : [ country, political ]
}
],
formatted_address : India,
geometry : {
bounds : {
northeast : {
lat : 35.5087008,
lng : 97.395561
},
southwest : {
lat : 6.7535159,
lng : 68.162386
}
},
location : {
lat : 20.593684,
lng : 78.96288
},
location_type : APPROXIMATE,
viewport : {
northeast : {
lat : 35.5087008,
lng : 97.395561
},
southwest : {
lat : 6.7535159,
lng : 68.16288519999999
}
}
},
place_id : ChIJkbeSa_BfYzARphNChaFPjNc,
types : [ country, political ]
}
],
status : OK
}
I have put my Required data where type is locality,political in **Required Text **
How can i get that

Used this method
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat: #"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray *arr=[[json valueForKeyPath:#"results.address_components"] objectAtIndex:0];
for (NSDictionary *dictAddress in arr)
{
if ([[dictAddress objectForKey:#"types"] count] > 0)
{
if([[[dictAddress objectForKey:#"types"] objectAtIndex:0] isEqualToString:#"locality"])
{
return [dictAddress objectForKey:#"long_name"];
}
else if([[[dictAddress objectForKey:#"types"] objectAtIndex:0] isEqualToString:#"political"])
{
return [dictAddress objectForKey:#"long_name"];
}
}
else
{
return #"";
}
}
return #"";
}
}
}];
Using this method you will find the name of the area which type start with "locality" or "political".
But i have took first object of the api response but if you need rathar than this , then put loop to take object of the json called.
Hope this will helps you.

You need to convert your string of the JSON object to an NSDictionary and then use key/value accessors to get each field.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat: #"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297, 76.444017]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray *results = [json valueForKey:#"results"];
for (NSDictionary *result in results)
{
NSLog(#"%#", [result valueForKey:#"formatted_address"]);
NSLog(#"%#", [result valueForKey:#"place_id"]);
// Etc...
}
}
}];

First off, I would use NSURLSessions and blocks to make network calls. The beauty of blocks is that if my network connection is poor my block will only get executed at after the call returns.
Then you need to convert your JSON to foundation objects that you can work with.
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",30.819297,76.444017];
NSURL *url = [NSURL URLWithString:urlString];
//Next we need a NSURLSession instance
NSURLSession *session = [NSURLSession sharedSession];
//All tasks (there are three, see documentation) are created from an NSURLSession instance
//We want a DataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//This "block" (of code) will be executed when the call is complete
//Serialize the JSON to Foundation objects
NSDictionary *geocodeDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//Parse through the JSON to get to where we want, address_components array
NSArray *resultsArray = geocodeDictionary[#"results"];
NSDictionary *resultsDictionary = resultsArray[0];
NSArray *addressComponents = resultsDictionary[#"address_components"];
//Declare variables to hold desired results
NSString *longName;
NSString *shortName;
//The address_components array contains many dictionaries,
//we loop through each dictionary and check the types array
for (NSDictionary *addressComponentDictionary in addressComponents) {
NSArray *typesArray = addressComponentDictionary[#"types"];
if ( [typesArray[0] isEqualToString:#"locality"]
&& [typesArray[1] isEqualToString:#"political"]) {
//the type IS locality and political
longName = addressComponentDictionary[#"long_name"];
shortName = addressComponentDictionary[#"short_name"];
}
}
//Test log to see we are correct
NSLog(#"%#", longName);
NSLog(#"%#", shortName);
}];
[dataTask resume];

Related

Filter NSArray of NSDictionary , where the dictionary is of type <key , NSDictionary>

I have a NSArray like this
[ {
"268" : { "name" : "abc", "age" : "28"} }, {
"267" : { "name" : "xyz","age" : "25"} } ]
Now I want to filter it on behalf of keys (means 268 , 267 ).
Eg : If user search for 7 then it need to show
[ { "267" : { "name" : "xyz","age" : "25"} } ]
let filterText : String = "7"
let array : [Dictionary<String,Any>] = [ ["268" : [ "name" : "abc", "age" : "28"]], [ "267" : [ "name" : "xyz","age" : "25"] ] ]
let result = array.filter { (dictinory) -> Bool in
if let firstKey = dictinory.keys.first {
return firstKey.contains(filterText)
}
return false
}
You can use NSPredicate with block in Objective-C to filter it:
NSString *searchText = #"8";
NSArray *data = #[#{ #"268" : #{ #"name" : #"abc", #"age" : #"28"} }, #{ #"267" : #{ #"name" : #"xyz",#"age" : #"25"}}];
NSPredicate *predicate = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) {
NSDictionary *dict = (NSDictionary *)obj;
NSString *key = dict.allKeys.firstObject;
return [key containsString:searchText];
}];
NSArray *filteredData = [data filteredArrayUsingPredicate:predicate];

What to send as beaconsData to getActionsForBeacons (Kontakt beacons)

I am using Kontakt beacons and iOS SDK and my code is again and again crashing at the part to get Actions for my beacons
Kontakt SDK docs are here
- (void)locationManager:(KTKLocationManager *)locationManager
didRangeBeacons:(NSArray *)beacons {
NSMutableDictionary *beaconsData = [NSMutableDictionary new];
for (CLBeacon *beacon in beacons) {
KTKBeacon *beaconData = [self _getDataForBeacon:beacon];
if (beaconData) [beaconsData setObject:beaconData forKey:beacon];
}
self.actionManager = [KTKActionManager new];
self.actionManager.delegate = self;
[self.actionManager processBeacons:beacons withData:beaconsData];
}
The method to get beacon Data
-(NSDictionary *)_getDataForBeacon:beacon
{
NSLog(#"%#",beacon);
NSData * jsonData = [NSData dataWithContentsOfURL:[NSURL
URLWithString:#"****"]];
NSError * error=nil;
NSDictionary *dic = [NSJSONSerialization
JSONObjectWithData:jsonData options:kNilOptions error:&error];
NSLog(#"%#",dic);
NSArray *array = [NSArray arrayWithObject:beacon];
NSDictionary *data = [self.client getActionsForBeacons:array changedSince:0 error:&error]; //##It crashes here##
NSLog(#"%#",data);
return data;
}
The contents of dic dictionary
{
"id" : "42152577-e3d2-4687-b499-8112402b2ca2",
"major" : 56809,
"txPower" : 3,
"browserActions" : [
],
"serial" : "",
"uniqueId" : "OFSP",
"interval" : 350,
"urlRequestActions" : [
],
"minor" : 57237,
"masterPassword" : null,
"password" : null,
"alias" : null,
"venue" : {
"id" : "f7fe1874-c9c2-4f88-980b-876681e2eb18",
"description" : "Flat room",
"rates" : [
],
"users" : [
],
"managers" : [
],
"priv" : true,
"beacons" : [
],
"lat" : null,
"beaconsCount" : 1,
"lng" : null,
"coverType" : null,
"name" : "Home"
},
"contentActions" : [
{
"actionType" : "CONTENT",
"beacon" : null,
"distance" : null,
"id" : "b0897c61-55c3-49c9-9f23-538f279ca1ce",
"owner" : {
"venues" : [
],
"password" : null,
"active" : false,
"id" : "307d0ef9-7207-47ec-980f-9382cff9b773",
"company" : {
"id" : "c95cc0fc-70fb-4a82-960c-c91845654fc8",
"name" : "Shubhank Gaur",
"key" : null
},
"email" : "shubhank008pp#gmail.com",
"salt" : null
},
"contentType" : "image\/jpeg",
"contentLength" : 354008,
"impairmentTypes" : [
],
"proximity" : "IMMEDIATE",
"contentCategory" : "IMAGE"
}
],
"proximity" : "f7826da6-4fa2-4e98-8024-bc5b71e0893e",
"name" : "Kontakt",
"actionsCount" : 1
}
And finally here is the error
2014-07-24 17:52:10.249 Code64Beacons[371:60b] -[CLBeacon identifier]:
unrecognized selector sent to instance 0x15593ef0
2014-07-24 17:52:10.250 Code64Beacons[371:60b] * Terminating app due
to uncaught exception 'NSInvalidArgumentException', reason: '-[CLBeacon
identifier]: unrecognized selector sent to instance 0x15593ef0'
* First throw call stack:
(0x30d00f0b 0x3b497ce7 0x30d04837 0x30d03137 0x30c52098 0xaa41b 0xa60b9
0xa5bd7 0xa85bf 0x311c5e91 0x311c0aeb 0x311ba081 0x30ccc01d 0x30ccb397
0x30cca001 0x30c34769 0x30c3454b 0x35ba16d3 0x33593891 0xa52cd 0x3b995ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)`
You might have resolved this as its too late. But below is the full code which you need to get the beacon data, might be useful for others running into this.
-(KTKBeacon *)_getDataForBeacon:(CLBeacon *)beacon
{
NSString *strURL = [NSString stringWithFormat:#"https://api.kontakt.io/beacon?proximity=%#&major=%#&minor=%#",
[beacon.proximityUUID UUIDString],
beacon.major,beacon.minor];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strURL]];
[request setValue:#"YOUR_API_KEY" forHTTPHeaderField:#"Api-Key"];
[request setValue:#"application/vnd.com.kontakt+json; version=2" forHTTPHeaderField:#"Accept"];
NSData *jsonData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError * error=nil;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#",dic);
KTKBeacon *newBeacon = [[KTKBeacon alloc] initWithDictionary:dic];
return newBeacon;
}

How do I filter array of dictionaries by dictionary key

Here is my JSON.This is for total 250 countries I listed only 3 below. here i need to do the thing is i have the parse the countries into seven different arrays based on continent.
{
"geonames" : [
{
"languages" : "ca",
"east" : 1.786542777831983,
"continent" : "EU",
"geonameId" : 3041565,
"population" : "84000",
"areaInSqKm" : "468.0",
"countryName" : "Andorra",
"south" : 42.42849259876837,
"countryCode" : "AD",
"capital" : "Andorra la Vella",
"isoAlpha3" : "AND",
"fipsCode" : "AN",
"isoNumeric" : "020",
"west" : 1.407186714111276,
"continentName" : "Europe",
"north" : 42.65604389629997,
"currencyCode" : "EUR"
},
{
"languages" : "ar-AE,fa,en,hi,ur",
"east" : 56.38166046142578,
"continent" : "AS",
"geonameId" : 290557,
"population" : "4975593",
"areaInSqKm" : "82880.0",
"countryName" : "United Arab Emirates",
"south" : 22.63332939147949,
"countryCode" : "AE",
"capital" : "Abu Dhabi",
"isoAlpha3" : "ARE",
"fipsCode" : "AE",
"isoNumeric" : "784",
"west" : 51.58332824707031,
"continentName" : "Asia",
"north" : 26.08415985107422,
"currencyCode" : "AED"
},
{
"languages" : "fa-AF,ps,uz-AF,tk",
"east" : 74.879448,
"continent" : "AS",
"geonameId" : 1149361,
"population" : "29121286",
"areaInSqKm" : "647500.0",
"countryName" : "Afghanistan",
"south" : 29.377472,
"countryCode" : "AF",
"capital" : "Kabul",
"isoAlpha3" : "AFG",
"fipsCode" : "AF",
"isoNumeric" : "004",
"west" : 60.478443,
"continentName" : "Asia",
"north" : 38.483418,
"currencyCode" : "AFN"
}
]
}
This is how you can filter your geonames array. the method filterArrayByADictionary gets an array and search criteria and returns filtered array of dictionaries.
-(NSArray *)filterArrayByADictionary:(NSArray *)aArray andKey:(NSString *)aPredicte
{
NSPredicate *filter = [NSPredicate predicateWithFormat:aPredicte];
return [aArray filteredArrayUsingPredicate:filter];
}
and you can call this method like this.
NSArray *AsiaCounties = [self filterArrayByADictionary: geonames andKey:#"continent = 'AS'"];
NSArray *EuropeCounties = [self filterArrayByADictionary: geonames andKey:#"continent = 'EU'"];
// rest of the continents...
Assuming you had taken this output in NSDictionary :
NSDictionary *mainDic;
NSMutableArray *arr = [NSMutableArray new];
NSMutableArray *arrcontinent1 = [NSMutableArray new];
NSMutableArray *arrcontinent2 = [NSMutableArray new];
arr = [mainDic valueForKey:#"geonames"];
for(int i=0; i<[arr count];i++){
NSDictionary *dic = [arr objectAtIndex:i];
if([[dic valueForKey:#"continent"] isEqualToString:#"EU"]){
[arrcontinent1 addObject:dic];
}
else if([[dic valueForKey:#"continent"] isEqualToString:#"AS"]){
[arrcontinent2 addObject:dic];
}
// and so on......
}

NSJSONSerialization parsing data issue

I am parsing below data:-
NSURL *URL = [NSURL URLWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=40.714353,-74.005973&destination=40.650000,-73.950000&sensor=false&units=metric&mode=transit&departure_time=1396594530&alternatives=true"];
NSData* data = [NSData dataWithContentsOfURL:URL];
NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
Only part of Result not full result showing:
2014-04-04 15:24:10.036 Animation[478:907] {
routes = (
{
bounds = {
northeast = {
lat = "40.715478";
lng = "-73.94947789999999";
};
southwest = {
lat = "40.6497484";
lng = "-74.01035299999999";
};
};
copyrights = "Map data \U00a92014 Google";
legs = (
{
"arrival_time" = {
text = "03:35"; <<----- missing "am"
"time_zone" = "America/New_York";
value = 1396596948;
};
"departure_time" = {
text = "03:02";<<----- missing "am"
"time_zone" = "America/New_York";
value = 1396594936;
};`
when use this on simulator Correct result is coming, again showing part of response :-
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 40.715478,
"lng" : -73.94947789999999
},
"southwest" : {
"lat" : 40.6497484,
"lng" : -74.01035299999999
}
},
"copyrights" : "Map data ©2014 Google",
"legs" : [
{
"arrival_time" : {
"text" : "3:35am", <<----- showing "am"
"time_zone" : "America/New_York",
"value" : 1396596948
},
"departure_time" : {
"text" : "3:02am",<<----- showing "am"
"time_zone" : "America/New_York",
"value" : 1396594936
}
And same code is working on simulator fine.
You can pass the language when calling the maps api. Setting the language to en_US leads to the desired result:
NSURL *URL = [NSURL URLWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=40.714353,-74.005973&destination=40.650000,-73.950000&sensor=false&units=metric&mode=transit&departure_time=1396594530&alternatives=true&language=en_US"];

How to parse JSON multi-array

I need to parse the JSON file provided by Google Maps API
Then i use the AFNetworkingRequestHow to get the JSON response.
I built this dictionary:
NSDictionary *jsonDict = (NSDictionary *) JSON;
NSArray *rows = [jsonDict objectForKey:#"rows"];
But now, how can i reach the first value field of duration tag?
JSON File to parse:
{
"destination_addresses" : [ "San Francisco, CA, USA", "Victoria, BC, Canada" ],
"origin_addresses" : [ "Vancouver, BC, Canada", "Seattle, WA, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "1,527 km",
"value" : 1527251
},
"duration" : {
"text" : "15 hours 0 mins",
"value" : 54010
},
"status" : "OK"
},
{
"distance" : {
"text" : "112 km",
"value" : 111906
},
"duration" : {
"text" : "3 hours 1 min",
"value" : 10885
},
"status" : "OK"
}
]
}
}
Try
NSDictionary *jsonDict = (NSDictionary *) JSON;;
NSArray *rows = jsonDict[#"rows"];
NSDictionary *row = rows[0];
NSArray *elements = row[#"elements"];
NSDictionary *element = elements[0];
NSDictionary *duration = element[#"duration"];
NSInteger value = [duration[#"value"] integerValue];
[json objectForKey:#"elements"]
is an NSArray. You can't initialize an NSDictionary directly with an array.
(in JSON, { and } denote key-value pairs, like NSDictionary, whereas [ and ] delimit ordered lists like NSArray, that's why the mapping is done as it is...)
Following thinks can you understanding for development time so it may help lot.
You can use the following code:
NSString *valueString = [[[[[rows objectAtindex:0]objectForKey:#"elements" ]objectAtindex:0]objectForKey:#"duration"] objectForKey:#"value"];
//if you want integer value
NSInteger value = [valueString integerValue];

Resources