In Below code run so i get a response from url but when i try to get encodedPoints it give me a null value. also i update RegexKitLite but prob. not solve. Any suggestion are welcome Thank you advance.
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
// http://maps.googleapis.com/maps/api/directions/json?origin=41.029598,28.972985&destination=41.033586,28.984546&sensor=false%EF%BB%BF%EF%BB%BF
NSURL *apiUrl = [NSURL URLWithString:[apiUrlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:nil error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
NSLog(#"encodedPoints: %#", encodedPoints);
if (encodedPoints) {
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
else {
return NO;
}
I think its not a good way to do API request synchronously, especially when user' phone has poor internet connection, it will slow down the responsiveness of your application. So you should do an asynchronous API request with NSURLSession.
Also, the Directions API might return more than one routes for your request. So its better to use a NSArray to store your polyline points.
Sample code:
- (void)getPolyline {
NSURL *url = [[NSURL alloc] initWithString:#"https://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&key=YOUR_API_KEY"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSError *jsonError;
NSDictionary *dict = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:data options:nil error:&jsonError];
if (!jsonError) {
NSArray *routesArray = (NSArray*)dict[#"routes"];
NSMutableArray *points = [NSMutableArray array];
for (NSDictionary *route in routesArray) {
NSDictionary *overviewPolyline = route[#"overview_polyline"];
[points addObject:overviewPolyline[#"points"]];
}
NSLog(#"%#", points);
}
} else {
//print error message
NSLog(#"%#", [error localizedDescription]);
}
}] resume];
}
Related
Hi fairly new to iOS just trying to connect the app to an API and get my token using Authentication. I have tried a lot of different options and just can't seem to get my head around it. All i'm trying to do is obtain my token. Can anyone see where I'm going wrong? The API documentation is here: https://simplybook.me/en/api/developer-api
NSURL *url = [NSURL URLWithString:#"http://user-api.simplybook.me/login/"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"myloginname" forHTTPHeaderField:#"X-Company-Login"];
[request setValue:#"mytokenhere" forHTTPHeaderField:#"X-Token"];
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
NSLog(#"%#", resultDict);
} else {
NSLog(#"%#", error);
}
}];
[downloadTask resume];
Instead of declaring NSURLSession like this:
NSURLSession *session = [NSURLSession sharedSession];
Try this instead:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"https://user-api.simplybook.me/login/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
And also, make sure you've declared the NSURLSessionDelegate protocol in your header file.
I will give you sample code for getting token but this is regarding to the access and refresh token.You can understand it very clearly now.
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)actionLogin:(id)sender {
[self loginForGettingAccessandRefreshToken];
}
-(void)loginForGettingAccessandRefreshToken
{
#try {
NSString *strUserName = [textUsername.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strPassword = [textPassword.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strParameters = [NSString stringWithFormat:#"client_id=roclient&client_secret=secret&grant_type=password&username=%#&password=%#&scope=dataEventRecords offline_access", strUserName, strPassword];
id param = strParameters;
NSLog(#"The param is - %#",param);
[GlobalShareClass postLoginDataToServer:BASEURL_LOGIN passParameters:param success:^(id res)
{
if([res isKindOfClass:[NSDictionary class]]){
NSDictionary *dictRes = [res copy];
NSString *strErrDesc = [NSString stringWithFormat:#"%#",[dictRes objectForKey:#"error_description"]];
if([[dictRes allKeys] containsObject:#"error_description"]){
dispatch_async(dispatch_get_main_queue(), ^{
//Dispaly UI
});
}
else{
NSString *strAccessToken = [dictRes objectForKey:#"access_token"];
NSString *strRefreshToken = [dictRes objectForKey:#"refresh_token"];
NSString *strTokenType = [dictRes objectForKey:#"token_type"];
NSString *sstrExpiresIn = [dictRes objectForKey:#"expires_in"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strRefreshToken forKey:#"refresh_token"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strAccessToken forKey:#"access_token"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *responseDict = [GlobalShareClass getDataFromToken:globalShare.strAccessToken];
NSString *strFetchedSub = [[NSUserDefaults standardUserDefaults] stringForKey:#"loginIdSub"];
globalShare.loginId = [responseDict objectForKey:#"sub"];
}
}
else{
NSLog(#"The res starts with array");
}
} failure:^(NSError *error) {
// error handling here ...
NSLog(#"%#", [error localizedDescription]);
dispatch_async(dispatch_get_main_queue(), ^{
//Showing Error
});
} passViewController:self];
}
#catch(NSException *exception){
NSLog(#"%#",[exception description]);
}
#finally{
}
}
}
GlobalShareClass.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface GlobalShareClass : NSObject{
NSMutableArray *arr;
}
#property (strong, nonatomic) NSMutableArray *arr;
+ (GlobalShareClass *)sharedInstance;
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc;
+ (NSDictionary *)getDataFromToken:(NSString *)strToken;
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse;
#end
GlobalShareClass.m
#import "GlobalShareClass.h"
#implementation GlobalShareClass
#synthesize arr;
+ (GlobalShareClass *)sharedInstance {
static GlobalShareClass* _shareInstane = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shareInstane = [[GlobalShareClass alloc] init];
//Incase array of initialization
_shareInstane.arr = [[NSMutableArray alloc] init];
});
return _shareInstane;
}
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc{
GlobalShareClass *globalShare = [GlobalShareClass sharedInstance];
__block id jsonResp;
NSData *data = [parameter dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *dataTask = [session uploadTaskWithRequest: request
fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(data == nil && error){
NSLog(#"uploadTaskWithRequest error: %#", error);
failurePost(error);
}
else{
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *strStatusCode = [NSString stringWithFormat:#"%ld",(long)[((NSHTTPURLResponse *)response) statusCode]];
if([strStatusCode isEqualToString:#"400"]){
successPost(jsonResp);
}
NSString *strStatusCodeResponse = [self strGetStatusResponseCode:strStatusCode];
if([strStatusCodeResponse length] > 0){
dispatch_async(dispatch_get_main_queue(), ^{
// Showing error
});
}else{
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if([jsonResp objectForKey:#"error"] || jsonResp == nil){
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertController:#"Error" :[jsonResp objectForKey:#"error_description"] passViewController:vc];
});
}
else
successPost(jsonResp);
}
}
}];
[dataTask resume];
}
+ (NSDictionary *)getDataFromToken:(NSString *)strToken {
NSDictionary *data;
NSString *encoded = [strToken componentsSeparatedByString:#"."][1];
data = [GlobalShareClass urlBase64Decode:encoded];
return data;
}
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse {
#try {
NSDictionary *returnDict;
NSString *output = [strToParse stringByReplacingOccurrencesOfString:#"-" withString:#"+"];
output = [output stringByReplacingOccurrencesOfString:#"_" withString:#"/"];
switch (output.length % 4) {
case 0:
case 1:
break;
case 2:
output = [output stringByAppendingString:#"=="];
break;
case 3:
output = [output stringByAppendingString:#"="];
break;
default:
break;
}
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:output options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(#"%#", decodedString);
NSData *data = [decodedString dataUsingEncoding:NSUTF8StringEncoding];
returnDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
return returnDict;
}
#catch (NSException *exception) {
NSLog(#"%#", [exception description]);
}
}
#end
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I can't find out the shortest path between two coordinates in map view. I have searched in stack overflow, but it shows me some algorithm not the exact iOS code for map view.How do I get it?
Thank you.
You can use Directions API given by Google Maps SDK.
Example:
https://maps.googleapis.com/maps/api/directions/json?origin=lat,long&destination=lat1,lon1
It takes source and destination latitude and longitude and returns a JSON object of routes and the distance for each route. You can select the shortest route and map it.
Here is reference of Google api document. Try it to yourself with api along with required and optional parameter. It is very interesting to use Google DirectionsService.
#swati i have implement the google map for find the shortest path like this: Please change the code and Objects according to you.
You can also refer the following URL: Google Map Documentations
-(void)drawRoute :(CLLocationDegrees)lat and: (CLLocationDegrees)lng{
if ([polyline isKindOfClass:[GMSPolyline class]]){
polyline = nil;
polyline.map = nil;
currentPoly.map = nil;
}
[polyline setMap:nil];
currentPoly.map = nil;
CLLocation *LocationAtual = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
[self fetchPolylineWithOrigin:currentLocation destination:LocationAtual completionHandler:^(GMSPolyline *polyline1)
{
if(polyline1)
polyline1.map = mapView;
}];
}
-(void)fetchPolylineWithOrigin:(CLLocation )origin destination:(CLLocation )destination completionHandler:(void (^)(GMSPolyline *))completionHandler
{
NSString *originString = [NSString stringWithFormat:#"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
NSString *destinationString = [NSString stringWithFormat:#"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];
NSString *directionsAPI = #"https://maps.googleapis.com/maps/api/directions/json?";
NSString *directionsUrlString = [NSString stringWithFormat:#"%#&origin=%#&destination=%#&mode=driving", directionsAPI, originString, destinationString];
NSURL *directionsUrl = [NSURL URLWithString:directionsUrlString];
NSURLSessionDataTask *fetchDirectionsTask = [[NSURLSession sharedSession] dataTaskWithURL:directionsUrl completionHandler:
^(NSData data, NSURLResponse response, NSError *error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error)
{
if(completionHandler)
completionHandler(nil);
return;
}
routesArray = [json objectForKey:#"routes"];
dispatch_sync(dispatch_get_main_queue(), ^{
currentPoly.map = nil;
NSString *points;
if ([routesArray count] > 0)
{
NSDictionary *routeDict = [routesArray objectAtIndex:0];
NSDictionary *routeOverviewPolyline = [routeDict objectForKey:#"overview_polyline"];
points = [routeOverviewPolyline objectForKey:#"points"];
}
GMSPath *path = [GMSPath pathFromEncodedPath:points];
polyline = [GMSPolyline polylineWithPath:path];
polyline.strokeWidth = 4.f;
polyline.strokeColor = [UIColor colorWithRed:0.2043 green:0.6188 blue:0.9986 alpha:1.0000];
polyline.geodesic = YES;
polyline.map = mapView;
currentPoly = polyline;
[self distance:place_Id];
if(completionHandler)
completionHandler(polyline);
});
}];
[fetchDirectionsTask resume];
}
=========================================================================
-(void)distance :(NSString*)placeId{
NSString *mainURL = #"https://maps.googleapis.com/maps/api/place/details/json?";
NSString *placeid = placeId;
NSString *key =#"Your Google Api Key"; // Write here your google API Key here
NSString *directionsUrlString = [NSString stringWithFormat:#"placeid=%#&key=%#",placeid, key];
mainURL = [mainURL stringByAppendingString:directionsUrlString];
NSURL *url = [NSURL URLWithString:mainURL];
NSMutableURLRequest *urlRequest =
[NSMutableURLRequest requestWithURL:url];
[urlRequest setTimeoutInterval:30.0f];
[urlRequest setHTTPMethod:#"GET"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 && error == nil){
NSMutableString *strResponse =[[NSMutableString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *data = [strResponse dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//NSLog(#"json=====%#",json);
deatils_result = [json objectForKey:#"result"];
}
else if ([data length] == 0 && error == nil)
{
//NSLog(#"Nothing was downloaded.");
}
else if (error != nil)
{
// NSLog(#"Error happened = %#", error);
}
}];
}
I make a call to the youtube API to get the title of a video. I then want to display the title of the video on the screen in a table. How do I access the title after the block has finished executing?
Here's the code to get the title
-(void)getVideoTitle:(NSString *)urlStr success:(void (^)(NSDictionary *responseDict))success{
urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/videos?part=contentDetails%%2C+snippet%%2C+statistics&id=%#&key={API_KEY}",urlStr];
NSURL *url = [[NSURL alloc] initWithString:urlStr];
// Create your request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// Send the request asynchronously
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
// Callback, parse the data and check for errors
if (data && !connectionError) {
NSError *jsonError;
NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
if (!jsonError) {
success(jsonResult);
// NSLog(#"Response from YouTube: %#", jsonResult);
}
}
}] resume];
}
Here's how I call the above function:
[self getVideoTitle:#"zB4I68XVPzQ" success:^(NSDictionary *responseDict){
NSArray *itemsArray = [responseDict valueForKey:#"items"];
NSDictionary *item = itemsArray[0];
NSDictionary* snippet = [item valueForKey:#"snippet"];
NSString *title = [snippet valueForKey:#"title"];
}];
How do I get access the title variable outside the block after the block has finished executing?
I have tried the following with no luck
dispatch_async(dispatch_get_main_queue(), ^{
[self updateMyUserInterfaceOrSomething];
});
In your code:
NSString* recievedTitle __block = nil; //title is here, after block below run
[self getVideoTitle:#"zB4I68XVPzQ" success:^(NSDictionary *responseDict){
NSArray *itemsArray = [responseDict valueForKey:#"items"];
NSDictionary *item = itemsArray[0];
NSDictionary* snippet = [item valueForKey:#"snippet"];
recievedTitle = [snippet valueForKey:#"title"]; //here you write it
// or
NSString *title = [snippet valueForKey:#"title"];
[self updateInterfaceWithTitle: title]
}];
///
- (void)updateInterfaceWithTitle:(NSString*)title{
//use title here
}
I have an iOS app with a table view and I want to get the table items from an extern php file which gives me a json string. Now I try to store the data from the php file to the data variable. Here is my code:
- (NSMutableArray *)data {
if(!_data){
_data = [[NSMutableArray alloc] init];
NSURLSession *session = [NSURLSession sharedSession];
NSString *url = [NSString stringWithFormat:#"http://www.example.net/something/bla.php"];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *errorCode = [json valueForKey:#"error"];
if([errorCode isEqualToString:#"e0"]){
NSArray *persons = [json objectForKey:#"persons"];
for (int i = 0; i < [persons count]; i++) {
NSString *person = [[persons objectAtIndex:i] objectForKey:#"name"];
[_data addObject:person];
}
}
NSLog(#"3.: %#", _data); // Full
}];
[dataTask resume];
NSLog(#"2.: %#", _data); // Empty
}
NSLog(#"1.: %#", _data); // Empty
return _data;
}
How can I return the result of the url session now? As you can see on my comments, the _data array is only filled on NSLog 3 and it is empty on 1 and 2. Would be nice if someone could tell me what I must change.
I am creating an app that uses Google Place. Before I used to use Yahoo's api and had to use a url that was responsible for local search that was provided by yahoo. The url was following:
http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=SF0DVEvV34G4GnXEDU4SXniaDebJ_UvC1G1IuikVz3vpOJrBpyD.VqCJCVJHMh99He3iFz1Rzoqxb0b7Z.0-
Now since yahoo's api is discontinued I have decided to switch over to Google Place. But I cannot find an Url to use. I just dowlod the framework and use the api key. Where can I find such url for Google Place.
Register for the Google Places API by following the linke provided below:
https://code.google.com/apis/console
Refer Code Link for places Auto Search
https://github.com/AdamBCo/ABCGooglePlacesAutocomplete
NSString *const apiKey = #"*****23xAHRvnOf2BVG8o";
NSString * searchWord = #"search some place "
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&types=establishment|geocode&radius=500&language=en&key=%#",searchWord,apiKey];
pragma mark - Network Methods
-(void)retrieveGooglePlaceInformation:(NSString *)searchWord withCompletion:(void (^)(BOOL isSuccess, NSError *error))completion {
if (!searchWord) {
return;
}
searchWord = searchWord.lowercaseString;
self.searchResults = [NSMutableArray array];
if ([self.searchResultsCache objectForKey:searchWord]) {
NSArray * pastResults = [self.searchResultsCache objectForKey:searchWord];
self.searchResults = [NSMutableArray arrayWithArray:pastResults];
completion(YES, nil);
} else {
NSString *urlString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&types=establishment|geocode&radius=500&language=en&key=%#",searchWord,apiKey];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jSONresult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (error || [jSONresult[#"status"] isEqualToString:#"NOT_FOUND"] || [jSONresult[#"status"] isEqualToString:#"REQUEST_DENIED"]){
if (!error){
NSDictionary *userInfo = #{#"error":jSONresult[#"status"]};
NSError *newError = [NSError errorWithDomain:#"API Error" code:666 userInfo:userInfo];
completion(NO, newError);
return;
}
completion(NO, error);
return;
} else {
NSArray *results = [jSONresult valueForKey:#"predictions"];
for (NSDictionary *jsonDictionary in results) {
}
//[self.searchResultsCache setObject:self.searchResults forKey:searchWord];
completion(YES, nil);
}
}];
[task resume];
}
}