I have a button to share a link. I'm using basically two calls:
openActiveSessionWithReadPermissions and requestNewPublishPermissions.
So this is the button action:
- (IBAction) shareFacebookButtonAction:(id)sender
if (![[FBSession activeSession] isOpen])
{
NSArray *permissions = #[#"read_friendlists", #"email"];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error)
{
if (FB_ISSESSIONOPENWITHSTATE([session state]))
{
[self _prepareShare];
}
else
{
// show alert view with error
}
}];
}
else
{
[self _prepareShare];
}
}
and with this I'm asking for publish permission, if no permissione are found in session
-(void) _prepareShare;
{
if ([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound)
{
[FBSession.activeSession
requestNewPublishPermissions:
[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error)
{
if (!error)
{
[self _share];
}
else
{
//error
}
}];
} else
{
[self _share];
}
}
_share just posts something
-(void) _share;
{
NSMutableDictionary *params_dict = [NSMutableDictionary dictionary];
// setting some params
[FBRequestConnection startWithGraphPath:#"me/feed" parameters:params_dict HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (result)
{
// sharing succedeed, do something
}
else if (error)
{
//sharing failed, do something else
}
}];
}
First time I try to share (already logged on FB in iOS6 and app already authorized) completion handler of openActiveSessionWithReadPermissions is being called twice:
once with FBSessionStateOpen and once with FBSessionStateOpenTokenExtended (from the openSessionForPublishPermissions call).
As a consequence, _share is also called twice, first time in the else part of _prepareShare (if I already have publish permissions) and the second time in the completion handler of openSessionForPublishPermissions.
So I have a double post on Facebook wall, just the first time I ever share in the app. I also had a crash report for FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed (I couldn't be able to make it happen again).
What is the proper way to handle this situation?
It appears that by design, Facebook SDK retains references to block handlers, even after they have been called. Thus, in your call to openActiveSessionWithReadPermissions the completion handler may be called numerous times, in case the session state changes. See Facebooks comment on this issue here.
As a work around, you might want to implement your own mechanism that ensures the handler is fired only once:
__block FBSessionStateHandler runOnceHandler = ^(FBSession *session,
FBSessionState status,
NSError *error) { /* YOUR CODE HERE */ };
...
[FBSession openActiveSessionWithReadPermissions:YOUR_PERMISSIONS
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
if (runOnceHandler) {
runOnceHandler(session, status, error);
runOnceHandler = nil;
}
}
];
You Can use this
- (IBAction)facebookBasti:(id)sender {
if(FBSession.activeSession.isOpen){
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
NSLog(#" Email = %#",[user objectForKey:#"email"]);
}
}];
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
}
else {
// try to open session with existing valid token
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_actions",#"email",
nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permissions];
[FBSession setActiveSession:session];
if([FBSession openActiveSessionWithAllowLoginUI:NO]) {
// post to wall
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
NSLog(#" Email = %#",[user objectForKey:#"email"]);
}
}];
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
} else {
// you need to log the user
NSLog(#"login");
[FBSession openActiveSessionWithPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
}];
}
}
}
and publishFacebook method
-(void)publishFacebook
{
NSMutableDictionary *postParams2= [[NSMutableDictionary alloc] initWithObjectsAndKeys:
haberLink, #"link",
#"abc.com", #"name",
title, #"caption",
desc, #"description",
nil];
[FBRequestConnection
startWithGraphPath:#"me/feed"
parameters:postParams2
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat: #"Shared Facebook"];
[[[UIAlertView alloc] initWithTitle:#"Shared Facebook"
message:alertText
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil]
show];
}
}];
}
Please read Upgrading from 3.0 to 3.1, in particular the paragraph Asking for Read & Write Permissions Separately. It seems like Facebook SDK is not meant to be used this way.
You are now required to request read and publish permission separately (and in that order). Most likely, you will request the read permissions for personalization when the app starts and the user first logs in. Later, if appropriate, your app can request publish permissions when it intends to post data to Facebook.
and
It is important that you do not simply attempt to call the two individual methods back-to-back to replace either of the deprecated functions.
I wonder how you managed to solve this issue. BTW, I get the same crash report (FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed).
Related
I am trying to get basic user information from facebook, using the following code
- (void)viewDidLoad
{
[super viewDidLoad];
if(![[FBSession activeSession] isOpen]){
NSLog(#"Creating new session");
[FBSession openActiveSessionWithPermissions:nil
allowLoginUI:NO
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self makeRequestForUserData];
}];
}else{
}
}
- (void) makeRequestForUserData
{
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSLog(#"user info: %#", result);
[self.txtDetails setText: [result string]];
//[[FBSession activeSession] closeAndClearTokenInformation];
} else {
NSLog(#"error %#", error.description);
}
}];
}
When closeAndClearToken is commented and allowLoginUI is set to NO or YES no error occurs and I get the data, problem is whether or not somebody is logged into fb, I get the data of last user who logged in. Where as when I uncomment closeAndClearToken I get following error:
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
this is a class method, with a completionHandler, where you will get the user. Just call this method anywhere and it should work, if you setup you app on facebook.
+ (void)requestFacebookDataWithCompletionHandler:(void (^)(NSDictionary *))handler {
// If the session state is any of the two "open" states when the button is clicked
if (FBSession.activeSession.state == FBSessionStateOpen
|| FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
[FBSession.activeSession closeAndClearTokenInformation];
if (handler) {
handler(nil);
}
// If the session state is not any of the two "open" states when the button is clicked
} else {
// Open a session showing the user the login UI
// You must ALWAYS ask for public_profile permissions when opening a session
[FBSession openActiveSessionWithReadPermissions:#[#"public_profile",#"email"]
allowLoginUI:YES
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error) {
[[FBRequest requestForMe] startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
if (handler) {
handler(user);
}
}
}];
DAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate sessionStateChanged:session state:state error:error];
}];
}
}
you will also have to add some methods in AppDelegate; but you will find those methods there:
https://developers.facebook.com/docs/facebook-login/ios/v2.0 . Hope it will work
I am trying to develop a simple app, which, retrieves data from Facebook, when the user connects to it.
I tried this code for it.
NSArray *permissions = [[NSArray alloc] initWithObjects:#"user_birthday",#"user_hometown",#"user_location",#"email",#"basic_info", nil];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"%#", [result objectForKey:#"gender"]);
NSLog(#"%#", [result objectForKey:#"hometown"]);
NSLog(#"%#", [result objectForKey:#"birthday"]);
NSLog(#"%#", [result objectForKey:#"email"]);
}];
But when I run this code, it gives an error "FBSDKLog: Error for request to endpoint 'me': An open FBSession must be specified for calls to this endpoint."
Thanks in advance, really appreciate your help.
The error is very appropriate, what it is trying to say is that request connection method should be called once the session is open.
Now your
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
method returns BOOL value true or false to specify you wether session is open or not(it tries to open synchronously). So first check the result of this call and the put it inside the code for fetching info. For eg.
if (FBSession.activeSession.isOpen)
{
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"%#", [result objectForKey:#"gender"]);
NSLog(#"%#", [result objectForKey:#"hometown"]);
NSLog(#"%#", [result objectForKey:#"birthday"]);
NSLog(#"%#", [result objectForKey:#"email"]);
}];
}
This should remove your error, but you still may not get the results.You may or may not get result on the very first call to this code but whenever the code for completion handler will be called, this method FBRequestConnection will also get called and at that time you'll get the results as it is an asynchronous call.
If it still doesn't work try this
if (FBSession.activeSession.isOpen)
{
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (error)
{
NSLog(#"error:%#",error);
}
else
{
// retrive user's details at here as shown below
NSLog(#"FB user first name:%#",user.first_name);
NSLog(#"FB user last name:%#",user.last_name);
NSLog(#"FB user birthday:%#",user.birthday);
}
}];
`(void)fbAccountConfigureWithBlock:(void (^)(id, NSString *))block
{
_block_data=block;
if(![SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"Please go to settings and add at least one facebook account."];
_block_data(nil,nil);
});
return;
}
ACAccountStore *store = [[ACAccountStore alloc]init];
ACAccountType *accountType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[store requestAccessToAccountsWithType:accountType
options:#{ACFacebookAppIdKey : FacebookAppId,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : #[#"email"]}
completion:^(BOOL granted, NSError *error)
{
if(granted){
NSArray *array = [store accountsWithAccountType:accountType];
if(!array.count){
dispatch_sync(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"Please go to settings and add at least one facebook account."];
_block_data(nil,nil);
});
}
else{
ACAccount *account = array[0];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:[NSURL URLWithString:#"https://graph.facebook.com/me"]
parameters: #{#"fields":#"id,first_name,last_name,name,email,picture.height(180).width(180)"}];
[request setAccount:account];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if(!error){
NSDictionary *userData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSLog(#"Facebook user data ----> %#",userData);
dispatch_async(dispatch_get_main_queue(), ^{
if(userData[#"error"] != nil)
[self attemptRenewCredentials:store account:account];
else
_block_data(userData,nil);
});
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:error.localizedDescription];
_block_data(nil,nil);
});
}
}];
}
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"We need permission to access your facebook account in order make registration."];
_block_data(nil,nil);
});
}
}];
}`
I'm making a "FBRequestConnection" to get all the friends that play the game...
When I update the SDK of Facebook to the last one, this stop working. Because It was working before.
I have no respond, no success, no error. Any ideas?
NSString *query = #"SELECT uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) AND is_app_user = 1";
// Set up the query parameter
NSDictionary *queryParam = [NSDictionary dictionaryWithObjectsAndKeys:query, #"q", nil];
// Make the API request that uses FQL
[FBRequestConnection startWithGraphPath:#"/fql"
parameters:queryParam
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (error) {
[self debug:[NSString stringWithFormat:#"Error: %#", [error localizedDescription]]];
} else {
[self debug:[NSString stringWithFormat:#"Result: %#", [result objectForKey:#"data"]]];
}
}];
-(void)fbLogin {
if (!_session.isOpen) {
// create a fresh session object
_session = [[FBSession alloc] init];
// if we don't have a cached token, a call to open here would cause UX for login to
// occur; we don't want that to happen unless the user clicks the login button, and so
// we check here to make sure we have a token before calling open
if (_session.state == FBSessionStateCreatedTokenLoaded) {
// even though we had a cached token, we need to login to make the session usable
[_session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// we recurse here, in order to update buttons and labels
[[NSNotificationCenter defaultCenter] postNotificationName:#"fbConnected" object:nil];
}];
}
[self populateUserDetails];
}
}
Thanks
Open the session with:
[FBSession.activeSession openWithCompletionHandler:^(FBSession * session, FBSessionState state, NSError * error){
if (!error){
}
}];
HI Im trying to enable a IBAction to post on an user's timeline while they have an active section. I am getting an error message stating; Implicit declaration of function "x" is invalid C99. I been reading posts about the issue but no luck and honestly I am not sure if I am doing this right at all. I updated the permissions on my fb app and got the object code from the Graph API Explorer but I dont know if Im implementing it right on my code.
Here is my post method:
-(void) aPost
{
NSMutableDictionary<FBGraphObject> *object =
[FBGraphObject openGraphObjectForPostWithType:#"website"
title:#"CR Taxi APP"
image:#"http://a4.mzstatic.com/us/r1000/047/Purple4/v4/05/cc/f2/05ccf23f-a409-1e73-a649-a5e6afc4e6eb/mzl.llffzfbp.175x175-75.jpg"
url:#"https://itunes.apple.com/cr/app/cr-taxi/id674226640?mt=8"
description:#"La nueva aplicaciĆ³n para llamar taxis!"];;
[FBRequestConnection startForPostWithGraphPath:#"{id_from_create_call}"
graphObject:object
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
// handle the result
}];
}
and this is my action method
- (IBAction)publishAction:(id)sender {
if ([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound) {
NSArray *writepermissions = [[NSArray alloc] initWithObjects:
#"publish_stream",
#"publish_actions",
nil];
[[FBSession activeSession]requestNewPublishPermissions:writepermissions defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *aSession, NSError *error){
if (error) {
NSLog(#"Error on public permissions: %#", error);
}
else {
**not on the code //( error on this one) aPost(aSession, error);
}
}];
}
else {
// If permissions present, publish the story
**not on the code //(not an error on this one) aPost(FBSession.activeSession, nil);
}
}
Please help!
Thank you!
I'd guess the compiler error is actually "Implicit declaration of function 'aPost' is invalid C99", although the formatting of your action method code is wonky as written. The compiler is only going to produce that error message the first time it encounters the function call to aPost.
aPost is written as a method that has no return and takes no arguments. You are trying to call it as a C function, passing it two arguments, which the compiler interprets as an entirely new function. As aPost is written with all the hard-coded strings, you probably just want to change the calls to aPost(arg1, arg2); to [self aPost]; (provided aPost and publishAction are in the same class).
Try this: might helps you
//Write This Line in your ViewController.h File
#property (strong, nonatomic) NSMutableDictionary *postParams;
//in View Controller.m File
- (void)viewDidLoad
{
self.postParams =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
[UIImage imageNamed:#"Default.png"], #"picture",
#"Facebook SDK for iOS", #"name",
#"build apps.", #"caption",
#"testing for my app.", #"description",
nil];
[self.postParams setObject:#"hgshsghhgsls" forKey:#"message"];
}
- (IBAction)SharePressed:(id)sender {
#try {
[self openSession];
NSArray *permissions =[NSArray arrayWithObjects:#"publish_actions",#"publish_stream",#"manage_friendlists",#"read_stream", nil];
[[FBSession activeSession] reauthorizeWithPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
/* handle success + failure in block */
if (![session isOpen]) {
[self openSession];
}
}];
[FBRequestConnection startWithGraphPath:#"me/feed" parameters:self.postParams HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,id result,NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:#"error: domain = %#, code = %d, des = %#",error.domain, error.code,error.description];
}
else
{
alertText=#"Uploaded Successfully";
[self ResetAllcontent];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result" message:alertText delegate:self cancelButtonTitle:#"OK!"
otherButtonTitles:nil]show];
}];
}
#catch (NSException *exception) {
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:#"Please Login" message:#"For Sharing on facbook please login with facbook" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
[alert show];
}
#finally {
}
}
- (void)openSession
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:
^(FBSession *session,
FBSessionState state, NSError *error) {
[appDelegate sessionStateChanged:session state:state error:error];
}];
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) &&
(accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 &&
(account = [fbAccounts objectAtIndex:0])){
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
}
}
//=====in your plist file do
URLTypes=>Item 0=> URL Schemes =>Item 0=>fbyourfacebookId
FacebookAppID-your facebookID
And yes dont forget to create facebook id at developer.facebook.com
and also give permissions as your need
- (IBAction)shareViaFacebook:(id)sender {
if (FBSession.activeSession.isOpen) {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:#"%#. Join on Linute.",self.userNameLabel.text], #"name",
//#"Build great social apps and get more installs.", #"caption",
locationString, #"description",
//#"http://www.linute.com/", #"link",
eventPicString, #"picture",//imageURL
nil];
// Make the request
[FBRequestConnection startWithGraphPath:#"/me/feed"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
// Link posted successfully to Facebook
NSLog(#"result: %#", result);
} else {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
NSLog(#"%#", error.description);
}
}];
}else{
FBSession *session = [[FBSession alloc] initWithPermissions:#[#"public_profile", #"email",#"user_friends",#"publish_actions"]];
[FBSession setActiveSession:session];
[session openWithBehavior:FBSessionLoginBehaviorWithFallbackToWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (FBSession.activeSession.isOpen) {
[self shareViaFacebook:nil];
}else{
[self shareViaFacebook:nil];
}
}];
}
I currently have a problem with my iOS application because I don't seem to be able to send requests to people...
Here is the code that I have:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:nil];
if([FBSession activeSession].isOpen) {
[FBWebDialogs presentRequestsDialogModallyWithSession:[FBSession activeSession] message:#"Join me." title:#"Invite" parameters:params handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
NSLog(#"%#", [FBSession activeSession]);
if (error)
NSLog(#"Error sending request.");
else {
if (result == FBWebDialogResultDialogNotCompleted)
NSLog(#"User canceled request.");
else if(result == FBWebDialogResultDialogCompleted)
NSLog(#"Request: %#", resultURL);
else
NSLog(#"Error unknown.");
}
}];
}
else {
[FBSession openActiveSessionWithReadPermissions:#[#"email"] allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if(session.isOpen) {
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions"] defaultAudience:FBSessionDefaultAudienceEveryone allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if(session.isOpen) {
[self showRequestForFacebook];
}
}];
}
}];
}
Every time I get a Request: (null). I get a request ID but nothing on the account. I looked at the sample in the Facebook SDK and I seem to have exactly the same. However, it works with the sample and not with my code.
Is there anything to change somewhere? Is it something on developers.facebook.com?
Edit: I forgot to say that in the same application I use a SLComposeViewController to share on Facebook and it works perfectly.
Thanks a lot! :)
NSString *query2 = [NSString stringWithFormat:#"SELECT uid, name, pic_square,is_app_user FROM user WHERE is_app_user = 1 AND uid IN " #"(SELECT uid2 FROM friend WHERE uid1 = me())"];
// Set up the query parameter
NSDictionary *queryParam2 = #{ #"q": query2 };
// Make the API request that uses FQL
[FBRequestConnection startWithGraphPath:#"/fql" parameters:queryParam2 HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
if (error) {
} else {
// NSLog(#"Result: %#", result);
// Get the friend data to display
NSArray *friendInfo = (NSArray *) result[#"data"];
NSLog(#"%#",friendInfo);
self.data=friendInfo;
[self constructDictionaryOfNumbers];
// Show the friend details display
}
}];
}