I have 60 address and I want to add the pin for every address. I want to use google maps and not Apple maps. I have a loop outside, and calling this method for 100 elements.
And some times I got this error: *** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array
And the error is not regular, I mean the error does not corresponds to an exact address. Sometimes I got 20 errors, sometimes 15,...
Does anyone know how to resolve it?
thank you
- (CLLocationCoordinate2D) getLocationFromAddress:(NSString*) address
{
NSError *error = nil;
NSString *lookUpString;
NSDictionary *jsonDict;
NSData *jsonResponse;
NSArray *locationArray;
lookUpString = [[NSString alloc] initWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true", address];
lookUpString = [lookUpString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
jsonResponse = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:lookUpString]];
jsonDict = [NSJSONSerialization JSONObjectWithData:jsonResponse options:kNilOptions error:&error];
locationArray = [[NSArray alloc] init];
locationArray = [[[jsonDict valueForKey:#"results"] valueForKey:#"geometry"] valueForKey:#"location"];
#try {
locationArray = [locationArray objectAtIndex:0];
NSLog(#" LOADING, %d, %d, %d", [locationArray count], [jsonDict count], [jsonResponse length]);
}
#catch (NSException *exception) {
NSLog(#"ERROR LOADING, %d, %d, %d", [locationArray count], [jsonDict count], [jsonResponse length]);
}
#finally {
}
NSString *latitudeString = [[NSString alloc] init];
latitudeString = [locationArray valueForKey:#"lat"];
NSString *longitudeString = [[NSString alloc] init];
longitudeString = [locationArray valueForKey:#"lng"];
NSString *statusString = [[NSString alloc] init];
statusString = [jsonDict valueForKey:#"status"];
double latitude = 0.0;
double longitude = 0.0;
if ([statusString isEqualToString:#"OK"])
{
latitude = [latitudeString doubleValue];
longitude = [longitudeString doubleValue];
}
else
NSLog(#"Something went wrong, couldn't find address");
_location.longitude = longitude;
_location.latitude = latitude;
return _location;
}
Related
I am calling receipt validation method in app delegate to check the renewable process. Its working fine in development mode but after releasing from app store its always returning yes, even though user have not purchase the product. Please Suggest what wrong I am doing. In sandbox mode its working fine but after release I found the issue that its always returning true. For validating receipt I am using below code
// Validate the receipt
+(BOOL ) getStoreReceipt:(BOOL)sandbox andTrasaction:(SKPaymentTransaction *)tractaion{
NSArray *objects;
NSArray *keys;
NSDictionary *dictionary;
BOOL gotreceipt = false;
#try {
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString = [self base64forData:receiptData];
NSLog(#"receiptString Value---->= %#",receiptString);
NSString *encReceipt = [receiptData base64EncodedStringWithOptions:0];
NSLog(#"receiptString Value ======>= %#",encReceipt);
if (receiptString != nil) {
NSString *strSharedSecrect = #"MY_Secrect_Key";
objects = [[NSArray alloc] initWithObjects:receiptString,strSharedSecrect, nil];
keys = [[NSArray alloc] initWithObjects:#"receipt-data",#"password", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
NSString *postData = [self getJsonStringFromDictionary:dictionary];
NSLog(#"postData Value---->= %#",receiptString);
NSString *urlSting = #"https://buy.itunes.apple.com/verifyReceipt";
// if (sandbox) urlSting = #"https://sandbox.itunes.apple.com/verifyReceipt";
dictionary = [self getJsonDictionaryWithPostFromUrlString:urlSting andDataString:postData];
NSLog(#"dictionary Value for receipt---->= %#",dictionary);
if ([dictionary objectForKey:#"status"] != nil) {
if ([[dictionary objectForKey:#"status"] intValue] == 0) {
gotreceipt = true;
}
}
}
}//623065
} #catch (NSException * e) {
gotreceipt = false;
return NO;
NSLog(#"NSException---->= %#",e);
}
if (!gotreceipt) {
NSLog(#"Not gotreceipt---->=");
objects = [[NSArray alloc] initWithObjects:#"-1", nil];
keys = [[NSArray alloc] initWithObjects:#"status", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
return NO;
}else{
BOOL isPurchased = [self PurchasedSubscriptionStatues:dictionary];
return isPurchased;
}
return NO;
}
Checking if pending for renewable is there or not...
+(BOOL)PurchasedSubscriptionStatues:(NSDictionary *)transactionReceipt
{
if ([[transactionReceipt allKeys] containsObject:#"pending_renewal_info"]) {
NSArray *arrData = [transactionReceipt objectForKey:#"pending_renewal_info"];
NSDictionary *dicPendinRenew = [arrData objectAtIndex:0];
if ([[dicPendinRenew allKeys] containsObject:#"expiration_intent"] || [[dicPendinRenew objectForKey:#"auto_renew_status"] integerValue]==0) {
return NO;
}else if ([[dicPendinRenew objectForKey:#"auto_renew_status"] integerValue]==1) {
return YES;
}else{
return NO;
}
}else{
return YES;
}
return NO;
}
Convert String To Dictionary
+(NSString *)getJsonStringFromDictionary:(NSDictionary *)dicVal
{
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dicVal options:NSJSONWritingPrettyPrinted error:&error];
NSString *postString = #"";
if (! postData) {
NSLog(#"Got an error: %#", error);
return nil;
}
else { postString = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
return postString;
}
}
Convert Dictionary to string
+(NSDictionary *) getJsonDictionaryWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *jsonString = [self getStringWithPostFromUrlString:urlString andDataString:dataString];
NSLog(#"getJsonDictionaryWithPostFromUrlString-->%#", jsonString); // see what the response looks like
return [self getDictionaryFromJsonString:jsonString];
}
+ (NSDictionary *) getDictionaryFromJsonString:(NSString *)jsonstring {
NSError *jsonError;
NSDictionary *dictionary = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:[jsonstring dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
if (jsonError) {
dictionary = [[NSDictionary alloc] init];
}
return dictionary;
}
//Request for post method to get the recipt
+ (NSString *) getStringWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *s = #"";
#try {
NSData *postdata = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postlength = [NSString stringWithFormat:#"%d", [postdata length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setTimeoutInterval:60];
[request setHTTPMethod:#"POST"];
[request setValue:postlength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postdata];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (data != nil) {
s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
#catch (NSException *exception) {
s = #"";
}
return s;
}
// from https://stackoverflow.com/questions/2197362/converting-nsdata-to-base64
+ (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
------------------------------------------------------------------------
I think your PurchasedSubscriptionStatues method has an error: if the receipt does not contain pending_renewal_info key, it returns YES. Try creating a new sandbox user and see if the receipt contains this key, if not - then this method should return NO in such case.
Also, you can try using some library that can manage InApp purchases, like RMStore, to ease on the receipt verification.
I am fetching 700.000 rows from a web service and my app is crashing after a while being terminated due to memory issue, it consumes about 1 GB of ram before it crashes, the code is fairly simple, I fetch the JSON, I put into an array, I loop the array and insert into core data and once done I save the context
the code is shown below
+ (void)fetchTillDataAll:(int)tillId :(int)startAtRow :(int)takeNoOfRows {
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillDataAll:tillId = %d, startAtRow = %d, takeNoOfRows = %d", tillId, startAtRow, takeNoOfRows);
}
NSString *finalURL = [NSString stringWithFormat:#"https://host.domain.com:5443/api/till/tilldatav2/%d?StartAtRow=%d&TakeNoOfRows=%d",tillId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillDataAll:Transport error %#", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillDataAll:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *tillBasicDataArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillDataAll:tillBasicDataArray count = %lu", (unsigned long)[tillBasicDataArray count]);
NSLog(#"WebServices:fetchTillDataAll:tillBasicDataArray looks like %#",tillBasicDataArray);
}
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
//NSManagedObjectContext *context =
//appDelegate.persistentContainer.viewContext;
//context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSPersistentContainer *container = appDelegate.persistentContainer;
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *tillBasicDataDict = Nil;
//Loop through the array and for each dictionary insert into local DB
// lets work on concurrency here
for (id element in tillBasicDataArray){
tillBasicDataDict = element;
NSString *itemId = [tillBasicDataDict objectForKey:#"itemId"];
NSString *brandId = [tillBasicDataDict objectForKey:#"companyId"];
NSString *languageId = [tillBasicDataDict objectForKey:#"languageCode"];
NSString *colorCode = [NSString stringWithFormat:#"%#", [tillBasicDataDict objectForKey:#"colorCode"]];
NSString *discountable = [tillBasicDataDict objectForKey:#"discountable"];
NSString *exchangeable = [tillBasicDataDict objectForKey:#"exchangeable"];
NSString *noos14 = [tillBasicDataDict objectForKey:#"noos14"];
NSString *sizeCode = [NSString stringWithFormat:#"%#", [tillBasicDataDict objectForKey:#"sizeCode"]];
NSString *taxGroup = [tillBasicDataDict objectForKey:#"taxGroupId"];
NSString *taxRegion = [tillBasicDataDict objectForKey:#"taxRegion"];
NSString *tradeItemDesc = [tillBasicDataDict objectForKey:#"tradeItemDesc"];
NSString *withTax = [tillBasicDataDict objectForKey:#"withTax"];
NSString *status = [tillBasicDataDict objectForKey:#"status"];
// Use Core Data FMD
NSManagedObject *newPimItem = Nil;
newPimItem = [NSEntityDescription
insertNewObjectForEntityForName:#"TillData"
inManagedObjectContext:context];
[newPimItem setValue:itemId forKey:#"itemId"];
[newPimItem setValue:brandId forKey:#"brandId"];
[newPimItem setValue:languageId forKey:#"languageCode"];
[newPimItem setValue:colorCode forKey:#"colorCode"];
[newPimItem setValue:discountable forKey:#"discountable"];
[newPimItem setValue:exchangeable forKey:#"exchangeable"];
[newPimItem setValue:noos14 forKey:#"noos14"];
[newPimItem setValue:sizeCode forKey:#"sizeCode"];
[newPimItem setValue:[NSNumber numberWithInt:[taxGroup intValue]] forKey:#"taxGroup"];
[newPimItem setValue:taxRegion forKey:#"taxRegion"];
[newPimItem setValue:tradeItemDesc forKey:#"tradeItemDesc"];
[newPimItem setValue:[NSNumber numberWithInt:[withTax intValue]] forKey:#"withTax"];
[newPimItem setValue:[NSNumber numberWithInt:[status intValue]] forKey:#"status"];
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillDataAll:ItemId in loop = %#", itemId);
NSLog(#"WebServices:fetchTillDataAll:newPimItem = %#", newPimItem);
NSLog(#"WebServices:fetchTillDataAll:CoreData error = %#", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Failure to save context: %#\n%#", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:#"hasTillData"];
[tillUserDefaults synchronize];
}
}];
}
}
}] resume];
}
What can I do minimize the foot print so that I am able to download the data? I absolutely must have the data locally in order to allow offline capabilities in the app
----- EDIT -----
After implementing splitting the NSArray into an array of array I still get the same problem, below if the new code as suggested:
split method
+ (NSArray *) splitIntoArraysOfBatchSize:(NSArray *)originalArray :(int)batchSize {
NSMutableArray *arrayOfArrays = [NSMutableArray array];
for(int j = 0; j < [originalArray count]; j += batchSize) {
NSArray *subarray = [originalArray subarrayWithRange:NSMakeRange(j, MIN(batchSize, [originalArray count] - j))];
[arrayOfArrays addObject:subarray];
}
return arrayOfArrays;
}
Looping through the array as follows
+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchPriceList:priceListId = %d", pricelistId);
}
NSString *finalURL = [NSString stringWithFormat:#"https://host.domain.com:5443/api/till/tillpricelistv2/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error != nil) {
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchPriceList:Transport error %#", error);
}
} else {
NSHTTPURLResponse *responseHTTP;
responseHTTP = (NSHTTPURLResponse *) response;
if(responseHTTP.statusCode != 200) {
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
}
} else {
NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
NSLog(#"WebServices:fetchPriceList:PricelistObjectArray looks like %#",priceListObjectArray);
}
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSPersistentContainer *container = appDelegate.persistentContainer;
NSArray *arrayOfArrays = [NWTillHelper splitIntoArraysOfBatchSize:priceListObjectArray :1000];
for(NSArray *batch in arrayOfArrays) {
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
NSDictionary *priceListObjectDict;
//Loop through the array and for each dictionary insert into local DB
for (id element in batch) {
priceListObjectDict = element;
NSString *currencyName = [priceListObjectDict objectForKey:#"currencyName"];
NSString *price = [priceListObjectDict objectForKey:#"price"];
NSString *priceIncTax = [priceListObjectDict objectForKey:#"priceIncTAX"];
NSString *validFrom = [priceListObjectDict objectForKey:#"validFromDate"];
NSString *validTo = [priceListObjectDict objectForKey:#"validToDate"];
NSString *itemId = [priceListObjectDict objectForKey:#"itemID"];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"YYYY-MM-dd'T'HH:mm:ss"];
NSDate *validToDate = [dateFormat dateFromString:validTo];
NSDate *validFromDate = [dateFormat dateFromString:validFrom];
if([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchPriceList:validToDate: >>>> %# <<<<", validToDate);
NSLog(#"WebServices:fetchPriceList:validFromDate: >>>> %# <<<<", validFromDate);
}
if([NWTillHelper isDebug] == 1) {
NSLog(#"PimItemListView:tableView:context = %#", context);
}
NSManagedObject *newPrlItem = Nil;
newPrlItem = [NSEntityDescription
insertNewObjectForEntityForName:#"PriceList"
inManagedObjectContext:context];
[newPrlItem setValue:itemId forKey:#"itemId"];
[newPrlItem setValue:validToDate forKey:#"validTo"];
[newPrlItem setValue:validFromDate forKey:#"validFrom"];
[newPrlItem setValue:price forKey:#"price"];
[newPrlItem setValue:priceIncTax forKey:#"priceIncTax"];
[newPrlItem setValue:currencyName forKey:#"currencyName"];
if ([NWTillHelper isDebug] == 1) {
NSLog(#"WebServices:fetchTillData:ItemId in loop = %#", itemId);
NSLog(#"WebServices:fetchTillData:newPrlItem = %#", newPrlItem);
NSLog(#"WebServices:fetchTillData:CoreData error = %#", error);
}
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Failure to save context: %#\n%#", [error localizedDescription], [error userInfo]);
abort();
} else {
NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
[tillUserDefaults setInteger:1 forKey:#"hasPriceList"];
[tillUserDefaults synchronize];
}
}];
}
}
}
}] resume];
}
It still raises to 2 GB and gets terminated, when the NSURLSession completion block hits memory usage is about 250, I assume that is after it downloads the entire data set into the NSArray, but after that when I want to write to core data all goes terribly wrong and it goes to 2 GB and gets terminated
Why is that?
First split up your large array into an array of arrays. Experiment with a good batch size that is not too large (that the app will crash) or too small (that will take a long time). I would suggest starting with 500. See here how do do this: What is an easy way to break an NSArray with 4000+ objects in it into multiple arrays with 30 objects each?. I assume you can turn that code into an array extension..
NSArray *arrayOfArrays = [tillBasicDataArray splitIntoArrayBatchSize:500];
Next you can enqueue many block that will each process only one of the many array and save it at the end.
for(NSArray *batch in arrayOfArrays){
[container performBackgroundTask:^(NSManagedObjectContext *context ) {
...
for (id element in batch){
...
each performBackgroundTask is enqueued into an internal operation and will process one at a time.
The rest of your code remains basically the same.
Hi all I need to display Polyline in MKapview. I have done that but I need to show Polyline based on route. I'm getting like below image if am using location did update then it comes good i am try to store latitude and longitude then next time i have to displayed previous Polyline in that time i am not getting, please help me
- (void)drowRoautLines_FromLocation:(CLLocationCoordinate2D)FromLocation ToLocation:(CLLocationCoordinate2D)ToLocation
{
MKPlacemark *source = [[MKPlacemark alloc]initWithCoordinate:FromLocation
addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:source];
[srcMapItem setName:#"Source"];
MKPlacemark *destination = [[MKPlacemark alloc]initWithCoordinate:ToLocation
addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *distMapItem = [[MKMapItem alloc]initWithPlacemark:destination];
[distMapItem setName:#"Destination"];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:distMapItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error)
{
[self ShowLoading:NO];
NSLog(#"response = %#",response);
NSLog(#"error = %#",error);
NSArray *arrRoutes = [response routes];
if (arrRoutes.count == 0)
{
//Show Error Message.
}
else
{
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[mapView addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
//NSLog(#"Rout Instruction : %#",[obj instructions]);
}];
}];
}
}];
}
Working on Map application, I want to find the Expected time to reach destination point without use any api like maps.google.
any help?
Below is the code :
MKPlacemark* placemark = [[MKPlacemark alloc] initWithCoordinate:new_coordinate addressDictionary:nil];
MKMapItem* destinationMapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
MKDirectionsRequest *request = [MKDirectionsRequest new];
request.source = [MKMapItem mapItemForCurrentLocation];
request.destination = destinationMapItem;
request.transportType = MKDirectionsTransportTypeAutomobile;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
MKRoute *route = response.routes.firstObject;
NSMutableString *Str = [NSMutableString new];
int counter = 1;
for (MKRouteStep *step in route.steps) {
[Str appendFormat:#"%d %#", counter, step.instructions];
counter++;
}
}];
No Error given but not called portion inside calculateDirectionsWithCompletionHandler..
I am getting a string response from the Google Directions API that contains characters that are supposed to represent a different-language character. Similiar to Ƨ³, similiar to these type of characters. I think the characters are portugese, but anyways my string contains like this:
\U00e3o
(I am not sure if those are zeroes or 'O's)
I am not sure what the technical term for these characters are, but how can I fix them in my string so they print properly.
Thank you
UPDATE:
I have updated my question title with the correct term 'unicode'.
I have checked a few questions:
NSString Unicode display
Detect Unicode characters in NSString on iPhone
iOS HTML Unicode to NSString?
And a few others. I have followed the answer, but the unicode characters are not fixed.
UPDATE:
Here is my code to get the response from GDirection.
Forming the request and getting a response:
AFHTTPClient *_httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://maps.googleapis.com/"]];
[_httpClient registerHTTPOperationClass: [AFJSONRequestOperation class]];
[_httpClient setDefaultHeader:#"Accept" value:#"application/json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location.coordinate.latitude, location.coordinate.longitude] forKey:#"origin"];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location2.coordinate.latitude, location2.coordinate.longitude] forKey:#"destination"];
[parameters setObject:#"false" forKey:#"sensor"];
[parameters setObject:#"driving" forKey:#"mode"];
[parameters setObject:#"metric" forKey: #"units"];
NSMutableURLRequest *request = [_httpClient requestWithMethod:#"GET" path: #"maps/api/directions/json" parameters:parameters];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
AFHTTPRequestOperation *operation = [_httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
if (statusCode == 200) {
[self parseResponse:responseObject];
} else {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
[_httpClient enqueueHTTPRequestOperation:operation];
}
Retrieving information from response object:
- (void)parseResponse:(NSDictionary *)response {
NSString *status = [response objectForKey: #"status"];
if (![status isEqualToString: #"OK"]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat: #"Google Directions Response Status: %#", status] delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[alert show];
}
else {
NSArray *routes = [response objectForKey:#"routes"];
NSDictionary *routePath = [routes lastObject];
if (routePath) {
NSString *overviewPolyline = [[routePath objectForKey: #"overview_polyline"] objectForKey:#"points"];
legs = [routePath valueForKey: #"legs"];
if (legs) {
/* DIRECTION SET ================================================================================================================================
*/
directionOverview = [[NSMutableDictionary alloc] init];
NSString *legsDis = [NSString stringWithFormat: #"%#", [[legs valueForKey: #"distance"] valueForKey: #"text"]];
NSString *kmDistance = [self cutStringToPreference: legsDis];
if (kmDistance) {
[directionOverview setObject:kmDistance forKey: #"distance"];
milesLabel.text = kmDistance;
milesLabel.font = [UIFont fontWithName:#"interstate" size: 20.0];
}
NSString *durationText = [NSString stringWithFormat: #"%#", [[legs valueForKey: #"duration"] valueForKey: #"text"]];
durationText = [self cutStringToPreference: durationText];
if (durationText) {
[directionOverview setObject:durationText forKey: #"duration"];
}
NSString *startAddress = [NSString stringWithFormat: #"%#", [legs valueForKey: #"start_address"]];
startAddress = [self cutStringToPreference: startAddress];
NSString *endAddress = [NSString stringWithFormat: #"%#", [legs valueForKey: #"end_address"]];
endAddress = [self cutStringToPreference: endAddress];
[directionOverview setObject:startAddress forKey: #"origin"];
[directionOverview setObject:endAddress forKey: #"destination"];
NSArray *steps = [legs valueForKey: #"steps"];
if (steps) {
instructionArray = [[NSMutableArray alloc] init];
durationArray = [[NSMutableArray alloc] init];
distanceArray = [[NSMutableArray alloc] init];
int number = [[[steps lastObject] valueForKey: #"html_instructions"] count];
for (int i = 1; i <= number; ++i) {
NSString *instruction = [[[steps lastObject] valueForKey: #"html_instructions"] objectAtIndex: i-1];
instruction = [self cutStringToPreference: instruction];
instruction = [self flattenHTML: instruction];
instruction = [self stringByDecodingHTMLEntitiesInString: instruction];
[instructionArray addObject: instruction];
NSString *distance = [[[[steps lastObject] valueForKey: #"distance"] objectAtIndex: i-1] valueForKey: #"text"];
[distanceArray addObject: distance];
NSString *duration = [[[[steps lastObject] valueForKey: #"duration"] objectAtIndex: i-1] valueForKey: #"text"];
[durationArray addObject: duration];
}
}
}
_path = [self decodePolyLine:overviewPolyline];
NSInteger numberOfSteps = _path.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [_path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
}
}
Displaying the text in a label:
NSString *overviewAddressText = [NSString stringWithFormat: #"%# to %#", [directionOverview objectForKey: #"origin"], [directionOverview objectForKey: #"destination"]];
overviewAddress.text = overviewAddressText;
UPDATE:
Image of label
So as you can see, in the label, the text contains this kind of substring: S/U00e3o, which is a word that has an unsupported character. How can I fix that so that unicode turns into this: São