I have a tab bar app with 3 tabs. On each one I implement FB through an UIActionSheet. When I debug on my phone, the first time I run the app it asks me to login, then says redirecting, and then the window disappears. I wait, but the publish to wall page won't show. If I click the button it will pull up the fb window and say redirecting and then close again. Then, if I close the app all the way, restart and click it; it does perfect. Any suggestions? Here's .m for one of the view controllers. All view controllers are same except for the void post to wall statement and of course the website they load in the viewdidload.
.m
UPDATE: If it would help I could email someone the source code to give me a hand with why the first time I login to facebook it won't redirect to the wall. Again, after I close the app and click the button again, then it will load to the wall.
UPDATE2: I just noticed that the TUAW App has this same problem. Try downloading that, or if you already have it, delete and redownload and then try to post to facebook and you'll see the exact same issue I'm describing.
UPDATE 3:
So I tried a suggestion I got in a PM and changed my code for the loginDialog to this:
It worked great...almost. On all of the view controllers that implement a facebook connect using the UIActionSheet, there were no problems. It logged in, grabbed the correct title and URL from the NSString, and pulled publish to wall on the first go.
The almost part requires a bit more info from me. I forgot that I have another View setup that uses FBConnect, but from an IBAction, not a UIActionSheet. If I leave the code
it will log in, then nothing. I have to stay logged in, restart the app, then click the button and since I'm still logged in it will pull the posttoWall correctly. If I change the code again to:
it crashes after I log in. What is the difference that is being caused by using IBAction and not UIActionSheet?
.m
Code:
#import "FirstViewController.h"
#import <QuartzCore/QuartzCore.h>
@implementation FirstViewController
@synthesize activity;
@synthesize postentry;
@synthesize currentURL;
@synthesize title;
@synthesize session = _session;
@synthesize postGradesButton = _postGradesButton;
@synthesize logoutButton = _logoutButton;
@synthesize loginDialog = _loginDialog;
@synthesize facebookName = _facebookName;
@synthesize posting = _posting;
@synthesize text;
- (IBAction)done {
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
-(IBAction)action:(id)sender {
UIActionSheet *popup1 = [[UIActionSheet alloc] initWithTitle:@"Share article with a friend..." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Email Entire Article", @"Email Link To Article", @"Facebook", nil];
[popup1 showInView:self.tabBarController.view];
[popup1 release];
}
- (void)actionSheet:(UIActionSheet *)popup1 clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
{self.currentURL = steve.request.URL.absoluteString;
self.text = [steve stringByEvaluatingJavaScriptFromString:@"document.body.innerText"];
Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
if (mailClass != nil)
{
if ([mailClass canSendMail])
{
[self displayComposerSheet2];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
break;
case 1:
{self.currentURL = steve.request.URL.absoluteString;
self.title = [steve stringByEvaluatingJavaScriptFromString:@"document.title"];
Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
if (mailClass != nil)
{
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
break;
case 2:
{self.currentURL = steve.request.URL.absoluteString;
self.title = [steve stringByEvaluatingJavaScriptFromString:@"document.title"];
_posting = YES;
// If we're not logged in, log in first...
if (![_session isConnected]) {
self.loginDialog = nil;
_loginDialog = [[FBLoginDialog alloc] init];
[_loginDialog show];
}
// If we have a session and a name, post to the wall!
else if (_facebookName != nil) {
[self postToWall];
}
// Otherwise, we don't have a name yet, just wait for that to come through.
}
break;
}
}
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:@"Your friend is sharing this article"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:@"friend@example.com"];
[picker setToRecipients:toRecipients];
// Fill out the email body text
NSString *emailBody = [[[[[[self.title stringByAppendingString:@"\n"] stringByAppendingString:@"\n"] stringByAppendingString:@"Click the link below to read this article by Jeff Jenkins"] stringByAppendingString:@"\n"] stringByAppendingString:@"\n"] stringByAppendingString:self.currentURL];
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
}
-(void)displayComposerSheet2
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:@"Your friend is sharing this article"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:@"friend@example.com"];
[picker setToRecipients:toRecipients];
// Fill out the email body text
NSString *emailBody = [[[@"Check out this article by Jeff Jenkins!" stringByAppendingString:@"\n"] stringByAppendingString:@"\n"] stringByAppendingString:self.text];
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:{
UIAlertView *cancelled = [[UIAlertView alloc] initWithTitle:@"Results" message:@"Email Was Cancelled" delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[cancelled show];
[cancelled release];}
break;
case MFMailComposeResultSaved:{
UIAlertView *saved = [[UIAlertView alloc] initWithTitle:@"Results" message:@"Email Draft Saved" delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[saved show];
[saved release];}
break;
case MFMailComposeResultSent:{
UIAlertView *sent = [[UIAlertView alloc] initWithTitle:@"Results" message:@"Email Sent" delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[sent show];
[sent release];
}
break;
case MFMailComposeResultFailed:{
UIAlertView *failed = [[UIAlertView alloc] initWithTitle:@"Results" message:@"Email Failed To Send, Please Check Internet Connection And Try Again." delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[failed show];
[failed release];
}
break;
}
[self dismissModalViewControllerAnimated:YES];
}
-(void)launchMailAppOnDevice
{
NSString *recipients = @"mailto:friend@example.com&subject=Your friend wants you to read this article";
NSString *body = @"&body=My Guest Information";
NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
- (void)touchesEnded: (NSSet *)touches withEvent: (UIEvent *)event {
for (UIView* view in self.view.subviews) {
if ([view isKindOfClass:[UITextField class]])
[view resignFirstResponder];
}
}
- (void)viewDidLoad {
[steve loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.316apps.com/jeffsblog.html"]]];
timer = [NSTimer scheduledTimerWithTimeInterval:(1.0/2.0) target:self selector:@selector(tick) userInfo:nil repeats:YES];
static NSString* kApiKey = @"REMOVEDFORPRIVACY";
static NSString* kApiSecret = @"REMOVEDFORPRIVACY";
_session = [[FBSession sessionForApplication:kApiKey secret:kApiSecret delegate:self] retain];
// Load a previous session from disk if available. Note this will call session:didLogin if a valid session exists.
[_session resume];
[super viewDidLoad];
}
-(void)tick {
if(!steve.loading)
[activity stopAnimating];
else
[activity startAnimating];
}
- (void)webView:(UIWebView *)steve didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connection Error" message:@"Sorry You Need an Internet Connection For This Application to Work" delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];
[alert show];
[alert release];
}
- (void)session:(FBSession*)session didLogin:(FBUID)uid {
[self getFacebookName];
}
- (void)session:(FBSession*)session willLogout:(FBUID)uid {
_logoutButton.hidden = YES;
_facebookName = nil;
}
#pragma mark Get Facebook Name Helper
- (void)getFacebookName {
NSString* fql = [NSString stringWithFormat:
@"select uid,name from user where uid == %lld", _session.uid];
NSDictionary* params = [NSDictionary dictionaryWithObject:fql forKey:@"query"];
[[FBRequest requestWithDelegate:self] call:@"facebook.fql.query" params:params];
}
#pragma mark FBRequestDelegate methods
- (void)request:(FBRequest*)request didLoad:(id)result {
if ([request.method isEqualToString:@"facebook.fql.query"]) {
NSArray* users = result;
NSDictionary* user = [users objectAtIndex:0];
NSString* name = [user objectForKey:@"name"];
self.facebookName = name;
_logoutButton.hidden = NO;
[_logoutButton setTitle:[NSString stringWithFormat:@"Facebook: Logout as %@", name] forState:UIControlStateNormal];
if (_posting) {
[self postToWall];
_posting = NO;
}
}
}
#pragma mark Post to Wall Helper
- (void)postToWall {
FBStreamDialog* dialog = [[[FBStreamDialog alloc] init] autorelease];
dialog.userMessagePrompt = @"Enter your message:";
dialog.attachment = [NSString stringWithFormat:@"{\"name\":\"%@\",\"href\":\"%@\",\"caption\":\"Check out this article by Jeff Jenkins\",\"description\":\"\",\"media\":[{\"type\":\"image\",\"src\":\"http://www.316apps.com/jeffjenkins.jpg\",\"href\":\"http://jeffajenkins.com\"}]}",
self.title, self.currentURL];
[dialog show];
}
#pragma mark Memory Cleanup
- (void)viewDidUnload {
self.postGradesButton = nil;
self.logoutButton = nil;
}
- (void)dealloc {
[_session release];
_session = nil;
[_postGradesButton release];
_postGradesButton = nil;
[_logoutButton release];
_logoutButton = nil;
[_loginDialog release];
_loginDialog = nil;
[_facebookName release];
_facebookName = nil;
[super dealloc];
}
@end
UPDATE2: I just noticed that the TUAW App has this same problem. Try downloading that, or if you already have it, delete and redownload and then try to post to facebook and you'll see the exact same issue I'm describing.
UPDATE 3:
So I tried a suggestion I got in a PM and changed my code for the loginDialog to this:
Code:
_loginDialog = [[FBLoginDialog alloc] initWithSession:_session];
The almost part requires a bit more info from me. I forgot that I have another View setup that uses FBConnect, but from an IBAction, not a UIActionSheet. If I leave the code
Code:
_loginDialog = [[FBLoginDialog alloc] init];
Code:
_loginDialog = [[FBLoginDialog alloc] initWithSession:_session];