Why does CLGeocoder crash upon call - objective-c

I want to convert an Address into a Location on the Mac for routing purposes.
I am using
[[CLGeocoder alloc] geocodeAddressString:#"1 Infinite Loop, Cupertino, CA 95014"
completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if(error){
NSLog(#"%#", error);
}
if(placemarks){
NSLog(#"%#", placemarks);
}
}];
Upon runtime the execution crashes with a Bad Excess on the snippets first line.
Does anyone has an idea on how to overcome this?

You need to init CLGeocoder.
CLGeocoder *geoCoder = [[CLGeocoder alloc] init];
[geoCoder geocodeAddressString:#"1 Infinite Loop, Cupertino, CA 95014"
completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if(error){
NSLog(#"%#", error);
}
if(placemarks){
NSLog(#"%#", placemarks);
}
}];

Related

Asynchronously Api calls and returning data outside the block

I don't understand why I am getting null array outside the block code, even though I am using __block keyword on my array.
I am successfully getting data from a backend api with following code
`-(void)getJsonResponse:(NSString *)urlStr success:(void (^)(NSArray *responseDict))success failure:(void(^)(NSError* error))failure
{
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:urlStr];
// Asynchronously API is hit here
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// NSLog(#"%#",data);
if (error)
failure(error);
else {
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// NSLog(#"%#",json);
success(json);
}
}];
[dataTask resume]; // Executed First
}`
Then in my function for returning the data I am using following
`- (NSArray *)get_data:(NSDictionary *)credentials{
NSString *urlStr =[ NSString stringWithFormat:#"http://test.com %#",credentials];
__block NSArray *jsonArray= [[NSArray alloc]init];
[self getJsonResponse:urlStr success:^(NSArray *responseArray) {
jsonArray = responseArray;
NSLog(#"%#",responseArray);
} failure:^(NSError *error) {
// error handling here ...
}];
NSLog(#"%#",jsonArray);
return jsonArray;
}
`
The issue here is although I am successfully getting data within getJsonResponse block, but when I am trying to return the response data array as function return I am getting null for jsonArray. I thought assigning __block infront of jsonArray should retain the data assign within the block code ?
The second approach is not to use Async way like following
`- (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
{
NSError __block *err = NULL;
NSData __block *data;
BOOL __block reqProcessed = false;
NSURLResponse __block *resp;
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable _data, NSURLResponse * _Nullable _response, NSError * _Nullable _error) {
resp = _response;
err = _error;
data = _data;
reqProcessed = true;
}] resume];
while (!reqProcessed) {
[NSThread sleepForTimeInterval:0];
}
*response = resp;
*error = err;
return data;
}`
That way its blocking the main thread whilst waiting for data.
I would suggest using the same approach of getJsonResponse for your get_data function:
- (void)get_data:(NSDictionary *)credentials finish:(void(^)(NSArray *data))finish{
NSString *urlStr =[ NSString stringWithFormat:#"http://test.com %#",credentials];
__block NSArray *jsonArray= [[NSArray alloc]init];
[self getJsonResponse:urlStr success:^(NSArray *responseArray) {
jsonArray = responseArray;
if (finish) {
finish(jsonArray);
}
} failure:^(NSError *error) {
// error handling here ...
}];
}

Retrieving resultant data from blocks

-(void) ReverseGeocode
{
CLGeocoder *geocoder=[[CLGeocoder alloc]init];
[geocoder reverseGeocodeLocation:self.toLocation
completionHandler:^(NSArray *placemarks, NSError *error){
if(error){
NSLog(#"Geocode failed with error: %#",error);
return;
}
if(placemarks &&placemarks.count>0){
CLPlacemark *placemark=placemarks[0];
NSDictionary *addressDictionary=placemark.addressDictionary;
NSString *Address=[addressDictionary objectForKey:(NSString*)
kABPersonAddressStreetKey];
NSString *City=[addressDictionary objectForKey:(NSString*)
kABPersonAddressCityKey];
NSString *State=[addressDictionary objectForKey:(NSString*)
kABPersonAddressStateKey];
NSString *Zip=[addressDictionary objectForKey:(NSString*)
kABPersonAddressZIPKey];
NSString *adress=[NSString localizedStringWithFormat:#"%# %# %# %# %#",
Address,City,State,#"United States",Zip];
// return adress;
}
}];
}
Above is a method for ReverseGeocoding.
I am trying to retrieve the final result, NSString adress. How can I do that. I have many such methods where I need to retrieve the data.
- (void)reverseGeocodeWithCompletionHandler:(void (^)(NSString *address))completionHandler {
[geocoder reverseGeocodeLocation:self.toLocation
completionHandler:^(NSArray *placemarks, NSError *error){
if(error) {
NSLog(#"Geocode failed with error: %#",error);
completionHandler(nil);
} else if {
if(placemarks &&placemarks.count>0) {
//...
NSString *adress=[NSString localizedStringWithFormat:#"%# %# %# %# %#",
Address,City,State,#"United States",Zip];
completionHandler(address);
}
}];
}
Call this method like this:
[obj reverseGeocodeWithCompletionHandler:^(NSString *address) {
NSLog(#"Address is = %#", address);
}];

NSURLConnection Asyncronous Request returns null

Followed a recently made YouTube tutorial try connecting to web address asynchronously.
Retuning null for the response, but the data length is greater than 0. I've seen other code that does both null & length checking, which I didn't throw, just NSLog'd them.
#implementation ViewController
-(void)fetchAddress:(NSString *)address {
NSLog(#"Loading Address: %#", address);
[iOSRequest requestToPath:address onCompletion:^(NSString *result, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
[self stopFetching:#"Failed to Fetch"];
NSLog(#"%#", error);
} else {
[self stopFetching:result];
NSLog(#"Good fetch: %#", result);
}
});
}];
}
- (IBAction)fetch:(id)sender {
[self startFetching];
[self fetchAddress:self.addressField.text];
NSLog(#"Address: %#", self.addressField.text);
}
-(void)startFetching {
NSLog(#"Fetching...");
[self.addressField resignFirstResponder];
[self.loading startAnimating];
self.fetchButton.enabled = NO;
}
-(void)stopFetching:(NSString *)result {
NSLog(#"Done Fetching %#", result);
self.outputLabel.text = result;
[self.loading stopAnimating];
self.fetchButton.enabled = YES;
}
#implementation iOSRequest
+(void)requestToPath:(NSString *)
path onCompletion:(RequestCompletionHandler)complete {
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:path]
cachePolicy:NSURLCacheStorageAllowedInMemoryOnly
timeoutInterval:10];
NSLog(#"path: %# %#", path, request);
[NSURLConnection sendAsynchronousRequest:request
queue:backgroundQueue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *result = [[NSString alloc] initWithData:
data encoding:NSUTF8StringEncoding];
if (complete) {
complete(result, error);
NSLog(#"result: %# %lu %#", result, (unsigned long)[data length], error);
}
}];
}
request is http://www.google.com>
response is null
data length is 13644
Not sure what is wrong... any suggestions?
Thanks to Josh Caswell for pointing in the right direction, but allowing me to figure it out myself.
Changed the initWithData encoding from NSUTF8StringEncoding to NSASCIIStringEncoding.
[NSURLConnection sendAsynchronousRequest:request
queue:backgroundQueue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *result = [[NSString alloc] initWithData:
data encoding:NSASCIIStringEncoding];
if (complete) {
complete(result, error);
NSLog(#"result: %# %lu %#", result, (unsigned long)[data length], error);
}
}];

can not get user info after doing authentication,facebookSDK, ios

I am trying to authenticate using facebook account by following
- (IBAction)logInByFaceBook:(id)sender {
NSLog(#"appDelegate.session.isOpen = %#",appDelegate.session.isOpen == 0 ? #"NO" : #"YES");
FBSessionLoginBehavior behavior = FBSessionLoginBehaviorForcingWebView;
appDelegate.session = [[FBSession alloc] init];
[appDelegate.session openWithBehavior:behavior
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[NSNumber numberWithBool:YES] forKey:#"didLogIn"];
data = [[SavedData alloc] initLogInInfo:dict];
[data saveLogInInfoToDisk];
if (session.isOpen) {
FBRequest *me = [FBRequest requestForMe];
NSLog(#"me is %#",[me description]);
[me startWithCompletionHandler: ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *my, NSError *error) {
NSLog(#"my is %#",[my description]);
}
];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
];
}
However, i cant not get my username back and the console is displaying
Error: HTTP status code: 400
my is (null)
By looking up this documentation, 400 means Invalid email address..... and my is null so that I can no extract the username at all.....
I dont know why this happens...I try with the same email address with facebookSDK sample code and it works properly...
Getting lost now....Can somebody point out what I am doing wrong or missing something.

What is wrong with this locking scheme

for (NSString * district in allLinedStrings) {
PO1(district);
[self.mainLock lock];
CLGeocoder * geocode= [[CLGeocoder alloc]init];
[geocode geocodeAddressString:district completionHandler:^(NSArray *placemarks, NSError *error )
{
for (CLPlacemark * thePlace in placemarks)
{
[self handlePlacemark:thePlace];
}
[self.mainLock unlock];
}];
}
I want to run geocodeAddressString synchronously and I do this. Somehow I got error of deadlock. But what's wrong?
If you are using NSLock: Calling the lock method twice on the same thread will lock up your thread permanently.
for (NSString * district in allLinedStrings) {
PO1(district);
[self.mainLock lock];
CLGeocoder * geocode= [[CLGeocoder alloc]init];
[geocode geocodeAddressString:district completionHandler:^(NSArray *placemarks, NSError *error )
{
for (CLPlacemark * thePlace in placemarks)
{
[self handlePlacemark:thePlace];
}
}];
[self.mainLock unlock];
}