Retrieving resultant data from blocks - objective-c-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);
}];

Related

FBSDKLoginManager keep Facebook login since get user info

I get user name and email using this (see below).
the problem, are that the login webview close, the call to initWithGraphPath:#"me" was done async, so user can see empty field by the time I get response to this call.
Is there a way to keep the facebook login webview open since the call to initWithGraphPath was completed?
Thanks!
-(void)loginButtonClicked_Facebook{
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
if ([result.grantedPermissions containsObject:#"email"]){
NSLog(#"result is:%#",result);
[self fetchUserInfo];
}
}
}];
}
-(void)fetchUserInfo{
if ([FBSDKAccessToken currentAccessToken]){
NSLog(#"Token is available : %#",[[FBSDKAccessToken currentAccessToken]tokenString]);
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, email"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error){
NSString *userName = [result valueForKey:#"name"];
NSString *email = [result valueForKey:#"email"];
self.tfName.text=userName;
self.tfEmail.text=email;
self.tfEmailConfirmation.text=email;
NSLog(#"resultis:%#",result);
}else{
NSLog(#"Error %#",error);
}
}];
}
}
//YOURCONTROLLER.M
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
NSString *getFbid;
NSString *getFbFirstName,*getFBlastName, *getFbemail,*getfbBirthday,*getfbGender,*getFBpHone,*getFBlocation,*getFBcountry;
- (void) loginButton: (FBSDKLoginButton *)loginButton
didCompleteWithResult: (FBSDKLoginManagerLoginResult *)result
error: (NSError *)error{
NSLog(#"facebook login button test");
}
- (void) loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
NSLog(#"facebook logout button test");
}
-(void)loginButtonClicked
{
NSUserDefaults *defFacebookData = [NSUserDefaults standardUserDefaults];
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"user_friends", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
DLog(#"Process error======%#",error.description);
indicators.hidden=YES;
[indicators stopAnimating];
} else if (result.isCancelled) {
DLog(#"Cancelled");
indicators.hidden=YES;
[indicators stopAnimating];
} else {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, link, first_name, last_name, picture.type(large), email, birthday, bio ,location ,friends ,hometown , gender ,friendlists"}]
startWithCompletionHandler:^(
FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error)
{
// NSLog(#"fetched user:%#", result);
// [self fetchingFacebookFriends];
[defFacebookData setObject:[result objectForKey:#"email"] forKey:#"fbEmail"];
[defFacebookData setObject:[result objectForKey:#"id"] forKey:#"fbID"];
//PASS ID
getFbid = [result objectForKey:#"id"];
NSLog(#"getFbid========>%#",getFbid);
//PASS FIRST NAME
getFbFirstName=[result objectForKey:#"first_name"];
NSLog(#"first======>%#",getFbFirstName);
//PASS LAST NAME
getFBlastName=[result objectForKey:#"last_name"];
NSLog(#"first======>%#",getFBlastName);
//PASS EMAIL
getFbemail=[result objectForKey:#"email"];
NSLog(#"first======>%#",getFbemail);
//PASS PHONE
getfbGender=[result objectForKey:#"gender"];
NSLog(#"first======>%#",getfbGender);
[defFacebookData setObject:[result objectForKey:#"name"] forKey:#"fbName"];
// Image
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:[NSString stringWithFormat:#"me/picture?type=large&redirect=false"]
parameters:nil
HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id fbImageResult,
NSError *error) {
NSString *strURL = [NSString stringWithFormat:#"%#",[[fbImageResult objectForKey:#"data"] objectForKey:#"url"]];
NSLog(#"strURL=====>%#",strURL);
[defFacebookData setObject:strURL forKey:#"fbImage"];
[defFacebookData synchronize];
NSDictionary *fbdict=[NSDictionary dictionaryWithObjectsAndKeys:getFbid,#"id",getFbFirstName,#"first_name",getFBlastName,#"last_name",getFbemail,#"email",getfbGender,#"gender",strURL,#"fbImage", nil];
NSLog(#"done=========>%#",fbdict);
UIStoryboard*storyboard=[AppDelegate storyBoardType];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
BOOL fblogin =[defaults boolForKey:#"KeyEditProfile"];
if (fblogin)
{
UIStoryboard*Storyboard=[AppDelegate storyBoardType];
DashboardVC* tabbarController = (DashboardVC*)[Storyboard instantiateViewControllerWithIdentifier:#"DashboardVCId"];
// tabbarController.dictFacebookdict =fbdict;
// tabbarController.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:tabbarController animated:YES];
}
else
{
EditFBVC *cpvc=(EditFBVC*)[storyboard instantiateViewControllerWithIdentifier:#"EditFBVCId"];
NSLog(#"get fb id ===%#",getFbid);
// cpvc.checkBtnclick =#"1";
cpvc.dictFacebookdict =fbdict;
cpvc.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:cpvc animated:YES];
} // [self facebookdataOnServer];
}];
}
else{
//[SVProgressHUD dismiss];
DLog(#"error is %#", error.description);
}
}];
}
}
}];
}

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);
}
}];

data parameter is nil error when checking internet connectivity

When launching my app it checks if user is subscribed. If it dosent detect an internet connection it crashes with the error:
Failed to retrieve subscription with error 'The Internet connection appears to be offline.' and responseString: (null)*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'
.m
[self getPath:path
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (![responseObject isKindOfClass:[NSDictionary class]])
{
failureBlock(#"Invalid response received");
return;
}
NSDictionary *responseDict = (NSDictionary *)responseObject;
if (responseDict[#"error"] == nil)
{
[self saveUserDict:responseDict];
successBlock(responseDict);
}
else
{
failureBlock(responseDict[#"error"]);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DebugLog(#"Failed to log in with error '%#' and response: %#", error.localizedDescription, operation.responseString);
failureBlock(#"An unknown error occurred");
}];
}
- (void)getSubscriptionWithSuccessBlock:(void (^)(NSDictionary *subscriptionDict))successBlock
failureBlock:(void (^)(id responseObject))failureBlock
{
static NSString *path = #"/api/subscription";
NSDictionary *parameters = #{
#"userId" : userDict[#"userId"],
#"token" : userDict[#"token"]
};
DebugLog(#"Getting subscription with parameters: %#", parameters);
[self getPath:path
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (![responseObject isKindOfClass:[NSDictionary class]])
{
failureBlock(#"Invalid response received");
return;
}
NSDictionary *subscriptionDict = (NSDictionary *)responseObject;
if (subscriptionDict[#"error"] == nil)
{
DebugLog(#"Successfully retrieved subscription");
successBlock(subscriptionDict);
}
else
{
failureBlock(responseObject);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DebugLog(#"Failed to retrieve subscription with error '%#' and responseString: %#", error.localizedDescription, operation.responseString);
id responseObject = [NSJSONSerialization JSONObjectWithData:operation.responseData
options:0
error:nil];
failureBlock(responseObject);
}];
}
You need to check for the error before proceeding with the below line. In case there is an error do not call JSONObjectWithData: method with null data.
[self getPath:path
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (![responseObject isKindOfClass:[NSDictionary class]])
{
failureBlock(#"Invalid response received");
return;
}
NSDictionary *responseDict = (NSDictionary *)responseObject;
if (responseDict[#"error"] == nil)
{
[self saveUserDict:responseDict];
successBlock(responseDict);
}
else
{
failureBlock(responseDict[#"error"]);
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (!error) {
DebugLog(#"Failed to retrieve subscription with error '%#' and responseString: %#", error.localizedDescription, operation.responseString);
id responseObject = [NSJSONSerialization JSONObjectWithData:operation.responseData
options:0
error:nil];
failureBlock(responseObject);
} else {
//handle the error scenario
failureBlock(#"error occured");
}
}];
check for internet connection with Reachability framework.

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];
}

Returning NSDictionary from async code block? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
returning UIImage from block
Hi I'm trying to return dictionary of json twitter data so i can use it in my application. How ever it is being called from a async block. I can not save it or return it any thoughts?
-(NSDictionary *)TweetFetcher
{
TWRequest *request = [[TWRequest alloc] initWithURL:
[NSURL URLWithString: #"http://search.twitter.com/search.json?
q=iOS%205&rpp=5&with_twitter_user_id=true&result_type=recent"] parameters:nil
requestMethod:TWRequestMethodGET];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse
*urlResponse,
NSError *error)
{
if ([urlResponse statusCode] == 200)
{
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseData
options:0 error:&error];
//resultsArray return an array [of dicitionaries<tweets>];
NSArray* resultsArray = [dict objectForKey:#"results"];
for (NSDictionary* internalDict in resultsArray)
NSLog([NSString stringWithFormat:#"%#", [internalDict
objectForKey:#"from_user_name"]]);
----> return dict; // i need this dictionary of json twitter data
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
Thnx in advance!
I feel like I've written a ton of this async code lately.
- (void)tweetFetcherWithCompletion:(void(^)(NSDictionary *dict, NSError *error))completion
{
NSURL *URL = [NSURL URLWithString:#"http://search.twitter.com/search.json?q=iOS%205&rpp=5&with_twitter_user_id=true&result_type=recent"];
TWRequest *request = [[TWRequest alloc] initWithURL:URL parameters:nil requestMethod:TWRequestMethodGET];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
if (error) {
completion(nil, error);
return;
}
//resultsArray return an array [of dicitionaries<tweets>];
NSArray* resultsArray = [dict objectForKey:#"results"];
for (NSDictionary* internalDict in resultsArray)
NSLog(#"%#", [internalDict objectForKey:#"from_user_name"]);
completion(dict, nil);
}
else {
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
completion(nil, error);
}
}];
}
So, instead of calling self.tweetDict = [self TweetFetcher];, you would call it this way.
[self tweetFetcherWithCompletion:^(NSDictionary *dict, NSError *error) {
if (error) {
// Handle Error Somehow
}
self.tweetDict = dict;
// Everything else you need to do with the dictionary.
}];