SLRequest performRequestWithHandler does not work in ios 6 - facebook

I am trying to build simple prototype where I post some text to my facebook account. I have read the ios 6 facebook integration documentation and came up with following code. Everything seems to work fine until I hit the last block where I create SLRequest object in method postTextToFacebook and try to execute performRequestWithHandler with handler block. Control never does inside the handler block. I am assuming that performRequestWithHandler call is not successful in this case. Any one have done with successfully? Here is code for your reference.
#import <Social/Social.h>
#import "ViewController.h"
#implementation ViewController
#synthesize facebookAccount;
#synthesize accountStore;
#synthesize textToPost;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(IBAction) postToFacebook:(id)sender
{
self.statusLabel.text = #"Logging in ...";
if(self.accountStore == nil)
{
self.accountStore = [[ACAccountStore alloc] init];
}
ACAccountType *facebookAccountType = [self.accountStore enter code hereaccountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSMutableDictionary *myOptions = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"172197712918906", ACFacebookAppIdKey,
[NSArray arrayWithObjects:#"email", #"user_about_me", #"user_likes", nil], ACFacebookPermissionsKey, ACFacebookAudienceFriends, ACFacebookAudienceKey, nil];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:myOptions completion:^(BOOL granted, NSError *error){
__block NSString *statusText;
if(granted)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
[myOptions setObject:[NSArray arrayWithObjects:#"publish_stream", nil] forKey:ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:myOptions completion:^(BOOL granted, NSError *error) {
__block NSString *statusText1;
if(granted && error == nil)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
[self postTextToFacebook];
statusText1 = #"Text Posted.";
}
else{
statusText1 = #"Publish Failed.";
}
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = statusText1;
});
}];
}
else{
statusText = #"Login Failed.";
NSLog(#"Error = %#",error);
}
}];
}
-(void) postTextToFacebook
{
NSDictionary *parameters = #{#"message":self.textToPost.text};
NSURL *feedURL = [NSURL URLWithString:#"https://graphs.facebook.com/me/feed"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:feedURL parameters:parameters];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSLog(#"Facebook request received, status code %d", urlResponse.statusCode);
NSString *response = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response data: %#", response);
//handle errors
if(error == nil)
{
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = #"text posted to facebook";
});
}
}];
}
#end

Your url should be
https://graph.facebook.com/me/feed
instead of
https://graphs.facebook.com/me/feed
I was having a same issue and got an NSURLErrorDomain -1003 error on it.

Related

How to wait then perform an action based on HTTPrequest response iOS

I have class that post a tweet to twitter using HTTP Post
here is a bit of code
PostTweet.h
#interface PostTweet : NSObject
- (void)postMyTweet;
#end
PostTweet.m
- (void)postMyTweet
{
accountStore = [[ACAccountStore alloc] init];
accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
userAccount = [allAccounts objectAtIndex:0];
userName = userAccount.username;
NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterInfoRequest setAccount:userAccount];
[twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
//show status after done
long result = [urlResponse statusCode];
//Let us say that every thing is ok and I got 200 response
if (result == 200)
{
NSLog(#"%ld",result);
}
}
];
}
}
else
{
NSLog(#"Not authorized");
}
}];
}
In my viewcontroller.m
- (void) actuallySendTweet
{
PostTweet * pt = [[PostTweet alloc] init];
[pt postTweet];
NSLog(#"Done");
}
The Question is: after calling The testMethod, How to wait for the http request response and I can do anything based on the response.
What happens now is that as soon as I call the testMethod the NSLog perform right away and does not wait for the http response.
First, if you wanted to coordinate two different threads dispatch_semaphore_t might be more appropriate than dispatch_group_t.
Second, and more importantly, you should not take an asynchronous method such as performRequestWithHandler, invoke it from the main queue in a synchronous manner. You never should be blocking the main queue.
Fortunately performRequestWithHandler gives us a handler block which we can use to perform actions after the tweet is done. In your comments, you say you simply want to update your HUD after the tweet, so you should do that performRequestWithHandler (dispatching that UI update back to the main queue, because, as the documentation says, "handler is not guaranteed to be called on any particular thread"):
- (void)postMyTweet
{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
ACAccount *userAccount = [allAccounts objectAtIndex:0];
NSURL *reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary *parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterRequest setAccount:userAccount];
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (error)
NSLog(#"tweet fail; error = %#", error);
else
{
long result = [urlResponse statusCode];
if (result == 200)
NSLog(#"%ld",result);
else
NSLog(#"Unexpected response: %#", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]]);
}
// Dispatch UI updates back to main queue
dispatch_async(dispatch_get_main_queue(), ^{
// do your MBProgressHUD stuff here
});
}];
}
}
else
{
NSLog(#"Not authorized");
}
}];
}
You also asked "How can I pass the HTTP response result to the viewcontroller?" You obviously do all of this in performRequestWithHandler, where you have the HTTP response (and the response data).
If you want postTweet to operate synchronously, then best practices would dictate that you don't submit it from the main queue (because, at the risk of sounding like a broken record, you never want to block the main queue). But you could have actuallySendTweet dispatch this tweet from a background queue, e.g.:
- (void) actuallySendTweet
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PostTweet * pt = [[PostTweet alloc] init];
[pt postTweetSynchronously];
NSLog(#"Done");
dispatch_async(dispatch_get_main_queue(), ^{
// Now do any UI updates you want here.
// For example, do your MBProgressHUD update here.
});
});
}
- (void)postTweetSynchronously
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
NSArray *allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
ACAccount *userAccount = [allAccounts objectAtIndex:0];
NSURL *reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary *parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterRequest setAccount:userAccount];
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
// do whatever you want here, perhaps updating some class properties
// now that we're done, signal the semaphore
dispatch_semaphore_signal(semaphore);
}];
}
}
else
{
NSLog(#"Not authorized");
dispatch_semaphore_signal(semaphore); // make sure to signal here, too
}
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
As here you are using completion block. The thread does not wait for the execution of block.
So it you want that execution of block should complete and precess the data before finishing the execution of method, you can use,
dispatch_group_t
I am editing your method for that,
- (void)postMyTweet
{
accountStore = [[ACAccountStore alloc] init];
accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if (granted)
{
allAccounts = [accountStore accountsWithAccountType:accountType];
if ([allAccounts count] > 0)
{
userAccount = [allAccounts objectAtIndex:0];
userName = userAccount.username;
NSURL * reqURL = [NSURL URLWithString:ENDPOINT_MEDIA_UPLOAD];
NSDictionary * parameter = [NSDictionary dictionaryWithObject:tweetTitle forKey:#"status"];
SLRequest *twitterInfoRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:reqURL
parameters:parameter];
[twitterInfoRequest addMultipartData:tweetImage withName:PARAM_MEDIA type:CONTENT_TYPE_MULTIPART_FORM_DATA filename:nil];
[twitterInfoRequest setAccount:userAccount];
[twitterInfoRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
//show status after done
long result = [urlResponse statusCode];
//Let us say that every thing is ok and I got 200 response
if (result == 200)
{
NSLog(#"%ld",result);
}
dispatch_group_leave(group);
}
];
}
}
else
{
NSLog(#"Not authorized");
dispatch_group_leave(group);
}
}];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
}
Now from this you can get idea.

Facebook integration iOS 6 Social/Accounts Frameworks

I want to code a singleton for facebook integration with iOS 6.
I use Social and Accounts Frameworks.
This my FacebookData.h :
#class FacebookData;
#protocol FacebookDataDelegate <NSObject>
#optional
- (void)FacebookDataDidLoadRequest:(NSDictionary *)result;
- (void)FacebookDataDidFailToLoadRequest:(NSError *)error;
#end
#interface FacebookData : NSObject{
NSString *facebookAppID;
ACAccountStore *facebookAccountStore;
ACAccountType *facebookAccountType;
ACAccount *facebookAccount;
BOOL readPermissionsGranted;
BOOL RequestPermissionsGranted;
}
#property (nonatomic) id delegate;
+ (FacebookData*)sharedFacebookData;
- (void)setAppID:(NSString *)appID;
- (NSString *)currentAppID;
- (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest;
- (void)loadRequest:(NSString*)theRequest;
#end
The most important methods of my FacebookData.m :
- (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest{
if(!readPermissionsGranted){
__block NSArray *facebookPermissions = #[#"read_stream", #"email"];
__block NSDictionary *facebookOptions = #{ ACFacebookAppIdKey : facebookAppID,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : facebookPermissions};
[facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted, NSError *error)
{
if (granted) {
readPermissionsGranted = YES;
[self requestPermissions:Permissions andLoadRequest:theRequest];
}
// If permission are not granted to read.
if (!granted)
{
NSLog(#"Read permission error: %#", [error localizedDescription]);
[self.delegate FacebookDataDidFailToLoadRequest:error];
readPermissionsGranted = NO;
if ([[error localizedDescription] isEqualToString:#"The operation couldn’t be completed. (com.apple.accounts error 6.)"])
{
[self performSelectorOnMainThread:#selector(showError) withObject:error waitUntilDone:NO];
}
}
}];
}else{
__block NSArray *facebookPermissions = [NSArray arrayWithArray:Permissions];
__block NSDictionary *facebookOptions = #{ ACFacebookAppIdKey : facebookAppID,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : facebookPermissions};
[facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted2, NSError *error)
{
if (granted2)
{
RequestPermissionsGranted = YES;
// Create the facebook account
facebookAccount = [[ACAccount alloc] initWithAccountType:facebookAccountType];
NSArray *arrayOfAccounts = [facebookAccountStore accountsWithAccountType:facebookAccountType];
facebookAccount = [arrayOfAccounts lastObject];
[self loadRequest:theRequest];
NSLog(#"Permission granted");
}
if (!granted2)
{
NSLog(#"Request permission error: %#", [error localizedDescription]);
[self.delegate FacebookDataDidFailToLoadRequest:error];
RequestPermissionsGranted = NO;
}
}];
}
}
- (void)loadRequest:(NSString*)theRequest{
__block NSDictionary *result= [[NSDictionary alloc]init];
// Create the URL to the end point
NSURL *theURL = [NSURL URLWithString:theRequest];
// Create the SLReqeust
SLRequest *slRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:theURL parameters:nil];
// Set the account
[slRequest setAccount:facebookAccount];
// Perform the request
[slRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (error)
{
// If there is an error we populate the error string with error
__block NSString *errorString = [NSString stringWithFormat:#"%#", [error localizedDescription]];
NSLog(#"Error: %#", errorString);
[self.delegate FacebookDataDidFailToLoadRequest:error];
} else
{
NSLog(#"HTTP Response: %i", [urlResponse statusCode]);
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
result = jsonResponse;
[self.delegate FacebookDataDidLoadRequest:jsonResponse];
}
}];
}
I use this singleton like this :
FacebookData *data = [FacebookData sharedFacebookData];
data.delegate = self;
[data setAppID:APPIDKEY];
[data requestPermissions:#[#"friends_location"] andLoadRequest:#"https://graph.facebook.com/me/friends?fields=id,name,location"];
This request with this permissions fails whereas the same method with permissions :#[#"email"] and request: https://graph.facebook.com/me/friends works perfectly.
This is the error that I can see in the console :
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
I can't find where the bug is, I don't know how to use tokens with these frameworks.
Thanks for your help !
IMO your LoadRequest URL is not correct
andLoadRequest:#"https://graph.facebook.com/me/friends?fields=id,name,location"];
SLRequest gives an oauth error even though its real problem with the URL. SLRequest doesn't support "?fields=id,name,location" directly in URL. You need to pass them as parameter in SLRequest
See the example below:
NSString* queryString = NULL;
queryString = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends", nil];
NSURL *friendsRequestURL = [NSURL URLWithString:queryString];
SLRequest *friendsRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET URL:friendsRequestURL
parameters:#{#"fields":#"id,name,location"}];
PS: I was facing the similar problem last night and cursing the facebook for given wrong error statement. But finally able to solve it at the end. :)

An active access token must be used to query information about the current user

I am trying to fetch user details but am currently unable to fetch images.This is the error I am getting:
{
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
}
This is my code:
if(!self.store)
{
ACAccountStore *store1 = [[ACAccountStore alloc] init];
self.store=store1;
[store1 release];
}
ACAccountType *fbAccountType =
[store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSArray * permissions = #[#"read_stream", #"publish_stream",#"email", #"user_birthday",#"publish_actions",#"user_photos"];
NSDictionary * dict = #{ACFacebookAppIdKey : #"my_key", ACFacebookPermissionsKey : permissions, ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};
// Request permission from the user to access the available Twitter accounts
[store requestAccessToAccountsWithType:fbAccountType options:dict completion:^(BOOL granted, NSError *error) {
__block NSString * statusText = nil;
if (granted) {
statusText = #"Logged in";
NSArray * accounts = [store accountsWithAccountType:fbAccountType];
store = [accounts lastObject];
account = [accounts objectAtIndex:0];
NSLog(#"account is: %#", account);
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me?fields=picture"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:nil];
request.account = account;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error) {
if(!error){
NSDictionary *list =[NSJSONSerialization JSONObjectWithData:data
options:kNilOptions error:&error];
NSLog(#"Dictionary contains: %#", list );
}
else{
//handle error gracefully
}
}];
}
If I use https://graph.facebook.com/me as url then it works fine. But I need the profile pic as well. What to do?
"fields" is a parameter, not a part of the URL itself. This works:
SLRequest *videoLimitsRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:[NSURL URLWithString:#"https://graph.facebook.com/me"]
parameters:#{#"fields": #"video_upload_limits"}];
FYI, token is added automatically when you attach account to the SLRequest.
you can run fql with accesstoken like this
https://graph.facebook.com/fql?q=SELECT name from user where uid = YourFAcebookID&access_token=ACCESSTOKEN
This will work for you.
This is a bit old but I forgot to answer then.
From FB api 3.2 onwards everything is managed within the api, for bot iOS 5 and 6 native login. Here is what I did:
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequest *request = [FBRequest requestWithGraphPath:#"me/albums" parameters:nil HTTPMethod:#"GET"];
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error)
{
if(!error)
{
NSDictionary *list =(NSDictionary*)result;
int flag = 0;
for (int index = 0; index < [[list objectForKey:#"data"] count];index++)
{
if ([[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"name"] isEqualToString:#"Profile Pictures"])
{
[self fetchAlbumImages:[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"id"]];
flag = 1;
}
}
if (flag == 0)
{
[self fetchAlbumImages:#"No Album"];
}
}
else
{
}
};
[newConnection addRequest:request completionHandler:handler];
//[self.requestConnection cancel];
[newConnection start];
[newConnection release];
}
- (void) fetchAlbumImages:(NSString*)albumId
{
if ([albumId isEqualToString:#"No Album"])
{
NSMutableArray *albumArray = [[NSMutableArray alloc]init];
[self performSelectorOnMainThread:#selector(sendRegistrationRequest:) withObject:albumArray waitUntilDone:YES];
[albumArray release];
}
else
{
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequest *request = [FBRequest requestWithGraphPath:[NSString stringWithFormat:#"%#/photos",albumId] parameters:nil HTTPMethod:#"GET"];
FBRequestHandler handler =
^(FBRequestConnection *connection, id result, NSError *error)
{
if(!error)
{
NSDictionary *list =(NSDictionary*)result;
NSMutableArray *albumArray = [[NSMutableArray alloc]init];
for (int index = 0; index < ([[list objectForKey:#"data"] count]<10?[[list objectForKey:#"data"] count]:10);index++)
{
[albumArray addObject:[[[list objectForKey:#"data"] objectAtIndex:index] objectForKey:#"source"]];
}
[self performSelectorOnMainThread:#selector(sendRegistrationRequest:) withObject:albumArray waitUntilDone:YES];
}
else
{
}
};
[newConnection addRequest:request completionHandler:handler];
//[self.requestConnection cancel];
self.requestConnection = newConnection;
[newConnection start];
[newConnection release];
}
}

facebook integration in iphone with Facebook sdk for ios5 and 6

i have use FAcebook sdk 3.0 to integrate facebook.I have use sample code "HelloFacebookSample"
to post status.
I have change in Info.plist file with my AppId.
I have problem that show armv7s,armv7 architecture problem.I even solve out that by "Build Active Architecture Only "to YEs.
I have code that show button for login/logout for facebook
#import "HFViewController.h"
#import "AppDelegate.h"
#import <CoreLocation/CoreLocation.h>
#interface HFViewController () <FBLoginViewDelegate>
#property (strong, nonatomic) IBOutlet UIButton *buttonPostStatus;
#property (strong, nonatomic) id<FBGraphUser> loggedInUser;
- (IBAction)postStatusUpdateClick:(UIButton *)sender;
- (void)showAlert:(NSString *)message
result:(id)result
error:(NSError *)error;
#end
#implementation HFViewController
#synthesize shareStringFb;
#synthesize buttonPostStatus = _buttonPostStatus;
#synthesize loggedInUser = _loggedInUser;
- (void)viewDidLoad {
[super viewDidLoad];
// Create Login View so that the app will be granted "status_update" permission.
self.buttonPostStatus.enabled = YES;
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
statusText.text=self.shareStringFb;
{
// if the session is closed, then we open it here, and establish a handler for state changes
}
}
-(IBAction)backClick:(id)sender
{
[self.view removeFromSuperview];
}
- (void)viewDidUnload {
self.buttonPostStatus = nil;
self.loggedInUser = nil;
[super viewDidUnload];
}
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
// first get the buttons set for login mode
self.buttonPostStatus.enabled = YES;
}
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
// here we use helper properties of FBGraphUser to dot-through to first_name and
// id properties of the json response from the server; alternatively we could use
// NSDictionary methods such as objectForKey to get values from the my json object
self.loggedInUser = user;
}
- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {
self.buttonPostStatus.enabled = NO;
}
// Post Status Update button handler
- (IBAction)postStatusUpdateClick:(UIButton *)sender {
// Post a status update to the user's feed via the Graph API, and display an alert view
// with the results or an error.
NSString *message = [NSString stringWithFormat:#"Updating %#'s status at %#",
self.loggedInUser.first_name, [NSDate date]];
[FBRequestConnection startForPostStatusUpdate:self.shareStringFb
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
[self showAlert:message result:result error:error];
self.buttonPostStatus.enabled = YES;
}];
self.buttonPostStatus.enabled = NO;
}
// Post Photo button handler
it show one button with login/logout in simulator but when i test in device it doesn't show that button.
Please any one can tell me what is problem?Why it not show that?Is there any other way to integrate Fb in ios 5 and 6 both.
Use for
this facebook sdk (3.1) for iOS6
ViewController.h
#import <FacebookSDK/FacebookSDK.h>
{
NSDictionary *dictionary;
NSString *user_email;
NSString *accessTokan;
NSMutableDictionary *fb_dict;
}
- (IBAction)btn_loginwithfacebook:(id)sender;
{
if (!FBSession.activeSession.isOpen)
{
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session,FBSessionState state, NSError *error)
{
if (error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else if(session.isOpen)
{
[self btn_loginwithfacebook:sender];
}
}];
return;
}
[FBRequestConnection startWithGraphPath:#"me" parameters:[NSDictionary dictionaryWithObject:#"picture,id,birthday,email,name,gender,username" forKey:#"fields"] HTTPMethod:#"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (!error)
{
if ([result isKindOfClass:[NSDictionary class]])
{
//NSDictionary *dictionary;
if([result objectForKey:#"data"])
dictionary = (NSDictionary *)[(NSArray *)[result objectForKey:#"data"] objectAtIndex:0];
else
dictionary = (NSDictionary *)result;
//NSLog(#"dictionary : %#",dictionary);
user_email = [dictionary objectForKey:#"email"];
[dictionary retain];
//NSLog(#"%#",user_email);//
}
}
}];
accessTokan = [[[FBSession activeSession] accessTokenData] accessToken];
//NSLog(#"%#",accessTokan);
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",accessTokan]]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
//NSLog(#"%#",str);
fb_dict = [str JSONValue];
[str release];}
FacebookAppID ::370546396320150
URL types
Item 0
URL Schemes
Item 0 ::fb370546396320150

Get facebook user details in ios 6 sdk?

How to retrieve facebook user details with ios 6 inbuilt facebook sdk? I tried few examples, but couldn't get work.
- (void) getFBDetails {
if(!_accountStore)
_accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookTypeAccount = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[_accountStore requestAccessToAccountsWithType:facebookTypeAccount
options:#{ACFacebookAppIdKey: #"514284105262105", ACFacebookPermissionsKey: #[#"email"]}
completion:^(BOOL granted, NSError *error) {
if(granted){
NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
_facebookAccount = [accounts lastObject];
NSLog(#"Success");
[self me];
}else{
// ouch
NSLog(#"Fail");
NSLog(#"Error: %#", error);
}
}];
}
- (void)me{
NSURL *meurl = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *merequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:meurl
parameters:nil];
merequest.account = _facebookAccount;
[merequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *meDataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#", meDataString);
}];
}
But this fails to grab data from facebook. My app id is correct.
This the error message I got
Error: Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: no stored remote_app_id for app" UserInfo=0x1d879c90 {NSLocalizedDescription=The Facebook server could not fulfill this access request: no stored remote_app_id for app}
Not sure if this will fix it or not, but have you set the Facebook App ID in your AppName-Info.plist file of your app?
The key required is FacebookAppID, which is of type String.
Try filling in your App ID there as well and see if it works.
In iOS6.0 ,you have to ask read and write permissions separately.
First ask for read permissions that is email then ask for other permissions according to the app requirement.
in .h file
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#property (nonatomic, strong) ACAccountStore *accountStore;
#property (nonatomic, strong) ACAccount *facebookAccount;
in .m file
- (void) getuserdetails
{
self.accountStore = [[ACAccountStore alloc]init];
ACAccountType *FBaccountType= nil;
//[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
if (! FBaccountType) {
FBaccountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
}
NSString *key =kFBAppId;
NSDictionary *dictFB = [NSDictionary dictionaryWithObjectsAndKeys:key,ACFacebookAppIdKey,#[#"email"],ACFacebookPermissionsKey, nil];
[self.accountStore requestAccessToAccountsWithType:FBaccountType options:dictFB completion:
^(BOOL granted, NSError *e)
{
if (granted)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:FBaccountType];
self.facebookAccount = [accounts lastObject];
NSLog(#"facebook account =%#",self.facebookAccount);
[self get];
}
else
{
NSLog(#"fb error %#",e.description);
dispatch_async(dispatch_get_main_queue(), ^
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"%#",e.description);
if([e code]== ACErrorAccountNotFound)
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Account not found"
message:msgSetUpFBAccount delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
else
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:msgFBAccessDenied
message:#"" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
});
NSLog(#"error getting permission %#",e);
}
}];
}
-(void)get
{
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:nil];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error)
{
if(!error)
{
list =[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"Dictionary contains: %#", list );
if([list objectForKey:#"error"]!=nil)
{
[self attemptRenewCredentials];
}
dispatch_async(dispatch_get_main_queue(),^{
});
}
else
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"error from get%#",error);
}
}];
}
-(void)attemptRenewCredentials{
[self.accountStore renewCredentialsForAccount:(ACAccount *)self.facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error){
if(!error)
{
switch (renewResult) {
case ACAccountCredentialRenewResultRenewed:
NSLog(#"Good to go");
[self get];
break;
case ACAccountCredentialRenewResultRejected:
{
NSLog(#"User declined permission");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"You declined permission" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
case ACAccountCredentialRenewResultFailed:
{
NSLog(#"non-user-initiated cancel, you may attempt to retry");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"non-user-initiated cancel, you may attempt to retry" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
default:
break;
}
}
else{
//handle error gracefully
NSLog(#"error from renew credentials%#",error);
}
}];
}
T**o get this code work the bundle Identifier with which you have registered your application with facebook and bundle identifier in application plist file should be same**