I'm trying to post a message to the users wall in out iOS app. The first time the user attempts to do this, the app switches to the Facebook app so they can sign in and accept our app. It then automatically goes back to our app as excepted. It then opens a UIWebView dialog (so the user can post their message to their wall), however an error message is shown in the dialog instead, saying "An error has occurred. Please try again later." Subsequent attempts to post the message work as expected, the issue only seems to occur immediately after signing in or accepting our app on Facebook.
Furthermore, when the error is shown, and the user clicks okay to dismiss the dialog, it then loads the user's wall showing all their friends posts, rather than closing the dialog.
Anybody know any solutions to this issue? I am working off the latest SDK.
Here is the code I use to login and display the dialog.
Authenciating session:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:
nil];
[facebook authorize:permissions];
[permissions release];
return NO;
}
return YES;
And the code to show the dialog:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
kAppId, #"app_id",
link, #"link",
imageURL, #"picture",
linkName, #"name",
caption, #"caption",
description, #"description",
nil];
[facebook dialog:#"feed" andParams:params andDelegate:self];
Solved the issue by just making a separate call after it returns back to our app.
Related
I'm having a problem while trying to post a picture on a FB Page I'm the admin. The picture is uploaded on my own account instead of my page.
Here's the code i'm using to do this:
- (void)apiGraphUserPhotosPost:(UIImage*)img withMessage:(NSString*)message {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSUInteger c;
for (c = 0; c < [gFBPageArray count]; c++)
{
if ([[[gFBPageArray objectAtIndex:c] objectForKey:#"name"] isEqualToString:[defaults objectForKey:#"FBPostAs"]])
break;
}
params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
img, #"picture", message, #"message", [[gFBPageArray objectAtIndex:c] objectForKey:#"access_token"], #"access_token",nil];
[[self facebook] requestWithGraphPath:[NSString stringWithFormat:#"/%#/photos", [[gFBPageArray objectAtIndex:c] objectForKey:#"id"]]
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
[defaults objectForKey:#"FBPostAs"] contains the name of the FB page where i want to upload the picture.
gFBPageArray contains the list of FB page where i have admin rights.
Am I doing something wrong?
I've done something similar with the /PageID/feed and /PageID/videos and it works well...
You can find your answer for this problem here: picture-post-to-facebook-ends-up-in-the-wrong-place
If you want I can put more details here (copy/past) the code.
I'm trying to use the Facebook iOS "feed" dialog call to allow my app's user to share something on their Facebook wall. When the facebook app is not installed, it attempts to let them authenticate within the app (presumably using a web view). The issue is that this dialog just disappears once they authenticate. I was expecting the web view to return to the "feed" sharing view.
How do I detect that they authenticated so that I can re-open the feed dialog?
I've added fbDidLogin to my app delegate, but it's not being called. (I wasn't sure if this would normally be called or not, but I read several people recommending this.)
SBJSON *jsonWriter = [SBJSON new];
// The action links to be shown with the post in the feed
NSArray* actionLinks = [NSArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:
#"More Videos",#"name",#"http://www.example.com/",#"link", nil], nil];
NSString *actionLinksStr = [jsonWriter stringWithObject:actionLinks];
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"Test Caption", #"caption",
#"Test Description", #"description",
#"https://s3.amazonaws.com/example/images/test.png",
#"source",
self.video.blogLink, #"link",
#"01234567890123", #"app_id",
actionLinksStr, #"actions",
nil];
[delegate facebook].sessionDelegate = delegate;
[[delegate facebook] dialog:#"feed" andParams:params andDelegate:self];
It turns out the issue is the same as those reporting that the dialog disappears immediately for them. There is a bug in the Facebook SDK in regards to handling error -999, with the solution described in this comment on SO.
I finally realized I was having the same issue (albeit manifesting slightly differently), when I started listening to the FBDialogDelegate's method:
- (void)dialog:(FBDialog*)dialog didFailWithError:(NSError *)error
The error description referenced the -999 error mentioned above, leading me to the answer. Luckily the code checked into github worked flawlessly. I just had to pull it into the SDK codebase and recompile the .a lib file, then include it into my project.
Did you implemented facebook protocol FBSession in your view controller ?
To detect that user is authenticated you have to call isSessionValid:
if (![[self.fbAppDelegate facebook] isSessionValid]) {
NSArray *permissions = [[NSArray alloc] initWithObjects:#"publish_stream",#"create_event",#"offline_access", nil];
[[self.fbAppDelegate facebook] authorize:permissions];
}
and authorize inApp:
[self authorizeWithFBAppAuth:NO safariAuth:NO];
I am trying to make a post on another user's wall using another user using FBConnect. I am using the embedded method of the iOS Facebook API (that is, I am forcing the browser to appear inside my app, so I am not leaving the application at all). This method works for posting into the wall of the same user, but doesn't work on the wall of another user.
self.facebook = [[[Facebook alloc] initWithAppId:self.appID andDelegate:self] autorelease];
if ([self.facebook isSessionValid]) {
[self proceedToPost];
}else{
NSArray *permissions = [NSArray arrayWithObjects:#"publish_stream", #"email", #"read_stream", #"manage_pages", nil];
[self.facebook authorize:permissions];
}
- (void)proceedToPost
{
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: #"aName", #"name",
self.appID, #"app_id",
self.title, #"caption",
self.link, #"link",
#"animateURL", #"picture",
nil];
[params setObject:"my-user-profile-id" forKey:#"to"];
[self.facebook dialog:#"feed" andParams:params andDelegate:self];
}
The problem is that authorization is done as expected, but when trying to actually post, I see an error message in the embedded browser "cannot post to user's wall".
Can anyone help me with this?
Did you request the publish_stream permission from the extended permissions?
From the documentation about publish_stream permission:
Enables your app to post content, comments, and likes to a user's
stream and to the streams of the user's friends. With this permission,
you can publish content to a user's feed at any time, without
requiring offline_access. However, please note that Facebook
recommends a user-initiated sharing model.
http://developers.facebook.com/docs/reference/api/permissions/
You can request permissons like this:
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_stream",
nil];
[facebook authorize:permissions];
[permissions release];
Thanks for reading.
I went through Facebook iOS SDK Feed Dialog issue after authentication but in vain.
What works:
I created a sample "Hello, World" app using the Facebook iOS Tutorial with the Feed Dialog. This tutorial works fine and I am able to see the post in my feed.
Problem:
When I integrated this code in my app, I don't get to see the Feed Dialog after the authentication when the control reaches back to my app.
Flow of control:
I have a UIImagePickerController showing a camera that takes a picture, then shows UIAlertView to indicate that the image is being uploaded, shows a UIAlertView to display the result returned from server, and then finally shows a UIActionSheet to display the different sharing options (share to Facebook, Twitter, etc.).
When the user hits "Share to Facebook", the following selector gets invoked:
- (void) initFacebook
{
//Init Facebook
facebook = [[Facebook alloc] initWithAppId:#"308136969223987" andDelegate:self];
//Check for access_token
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
if(![facebook isSessionValid]) {
[facebook authorize:nil];
}
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
kAppId, #"app_id",
#"https://developers.facebook.com/docs/reference/dialogs/", #"link",
#"http://fbrell.com/f8.jpg", #"picture",
#"Facebook Dialogs", #"name",
#"Reference Documentation", #"caption",
#"Using Dialogs to interact with users.", #"description",
#"Facebook Dialogs are so easy!", #"message",
nil];
[_facebook dialog:#"feed" andParams:params andDelegate:self];
}
This launches the Facebook app to authenticate, and then opens my app again with the UIImagePickerController but doesn't show the Feed Dialog.
Can someone please help me out?
You have to manually call the method you want again, in your case -(void)initFacebook, in the -(void)fbDidLogin of the FBSessionDelegate.
In addition, to make this more generic, a little trick I did after [facebook authorize:nil]; I set a pending target and selector to store the pending command that needs to be executed after login. Something like this...
id fbPendingTarget;
SEL fbPendingAction;
if (![delegate.facebook isSessionValid]) {
[delegate.facebook authorize:nil]; // Facebook app or Safari login, mustitask
// Save pending actions
delegate.fbPendingTarget = self;
delegate.fbPendingAction = #selector(facebookButtonPressed);
[self retain]; // *** hold on to self if you will release self and is using fbPendingTarget as self
}
and when the delegate fires, it runs your pending action ...
- (void)fbDidLogin {
[self storeAuthData:[facebook accessToken] expiresAt:[facebook expirationDate]];
[self apiFQLIMe]; // request user info
// perform any pending actions after login
if ([fbPendingTarget respondsToSelector:fbPendingAction]) {
[fbPendingTarget performSelector:fbPendingAction];
}
self.fbPendingTarget = nil;
self.fbPendingAction = nil;
[self release]; // *** let go of self after we finished everything
}
This help executing any pending actions you need after login. And don't forget to clear them after executing or login failed.
-(void)fbDidNotLogin:(BOOL)cancelled {
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Cannot Connect"
message:#"There was an error while connecting to Facebook. Please try Again."
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil] autorelease];
[alertView show];
self.fbPendingTarget = nil;
self.fbPendingAction = nil;
[self release]; // *** let go of self after we finished everything
}
Hope this helps :)
Edit: I find it better to set fbPendingTarget to some object that exists throughout the app lifetime (like appDelegate) rather than setting to self. This is because in many cases your self is a view that will be released right after the user sends a post to Facebook. Sending a message to a released object will crash your app.
A dirty way to get around this is to explicitly use [self retain] before sending and then [self release] in your fbPendingAction. But that would retain everything else that should be released in self by that time. I just find it easier to set to appDelegate since most action you will do is just displaying an alert anyway. I'll edit the code just for safety sake.
I'd be grateful for any suggestions as to how to deal with a problem I'm having posting an image to Facebook.
The following code works just as I would expect:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"http://myserver/img.png", #"picture",
#"My Testing", #"name",
#"Enter some text...", #"message",
nil];
[appDelegate.facebook dialog:#"feed" andParams:params andDelegate:self];
However, I really want to use an image that I capture from my camera. I've set up the code to do that earlier in my application and I've put the image on the screen. So, I tried to do this:
CGRect contextRect = CGRectMake(0, 0, 320, 436);
UIGraphicsBeginImageContextWithOptions(contextRect.size, YES, 1);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I've tested this code and newImage is a valid UIImage that I can place and manipulate just as I'd expect. However, when I try to integrate it into the Facebook dialog as follows:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
newImage, #"picture",
#"My Testing", #"name",
#"Enter some text...", #"message",
nil];
[appDelegate.facebook dialog:#"feed" andParams:params andDelegate:self];
I get these two ridiculous messages in the console:
-[UIImage length]: unrecognized selector sent to instance 0x1c9420
CoreAnimation: ignoring exception: -[UIImage length]: unrecognized selector sent to instance 0x1c9420
So, as a test, I thought I'd try importing an image into my project and accessing it directly. This is the exact image as I referenced online in the first example, so I know it should work. But even when I try this:
UIImage *newImage = [UIImage imageNamed:#"BaB.png"];
I get the same error messages as above.
I see in the Facebook documentation that the "picture" key is supposed to use the URL to an image. But I've seen some examples online that indicate that folks are using an UIImage instead of just an URL.
Clearly, I'm doing something wrong, but I have no idea what it might be.
I'd be very grateful for any pointers as to how to proceed.
A summarized answer that outlines the process...key point is to include the access_token in the graph calls since the facebook-ios-sdk doesn't do this automatically:
1)Update to the latest facebook-ios-sdk.
2)Instantiate with app id.
self.facebook = [[Facebook alloc] initWithAppId:kApplicationFBID];
3) Authorize the app including publish_stream
NSArray * neededPermissions = [[[NSArray alloc] initWithObjects:#"user_about_me", #"publish_stream", #"user_photos", nil] autorelease];
[facebook authorize:neededPermissions delegate:appDelegate];
4) Ensure app delegate fBDidLogin captures and stores the access token & expiration in user defaults (for later optimization of login process).
-(void)fbDidLogin {
DebugLog(#"New Access Token: %#", [facebook accessToken] );
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
5) Confirm valid access token (non nil and not expired)...otherwise re authorize app per above.
6) Capture image to UIImage & call this noting the critical addition of the access_token. This will auto create an album for your app and put the image there and post it on the wall per my testing.
-(void)postImageToAlbum:(UIImage *)image {
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
image, #"source",
#"caption desc", #"message",
nil];
[facebook requestWithGraphPath:[NSString stringWithFormat:#"/me/photos?access_token=%#", self.facebook.accessToken]
andParams:params andHttpMethod:#"POST" andDelegate:self];
}
7) Check for id result in FBRequestDelegate method
-(void)request:(FBRequest *)request didLoad:(id)result {
NSLog(#"Request didLoad: %# ", [request url ]);
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
if ([result isKindOfClass:[NSDictionary class]]){
}
if ([result isKindOfClass:[NSData class]]) {
}
NSLog(#"request returns %#",result);
}
8) DO NOT USE a test user account for testing...currently it will auth the test account and provide an access token but when you try to use graph api it will return unexpected errors. You may be alright if you are using web version vs native app setting in dev.facebook.com since supposedly you can create test users and associate them with the app but I haven't tried that.
Good Luck!