Facebook的FBConnect SDK在iOS上发布

时间:2011-08-17 18:01:30

标签: iphone objective-c ios facebook fbconnect

我正在使用FBConnect sdk,以便通过我的应用程序将帖子发布到用户的个人资料中。我遇到了很多问题:

当相关代码首次在设备上运行时,用户会根据需要重定向到Facebook应用/网站,要求他对其进行授权。如果用户授权它,它会返回到应用程序,弹出“连接到Facebook”视图控制器,要求用户登录。这很奇怪,因为用户已经登录,否则他怎么能授权应用程序?但我想这可能没问题,因为他还没有通过应用程序登录。登录后,它什么也没做。只有第二次运行代码,在授权应用程序后,用户才能获得发布对话框。

如果用户没有授权应用程序,当它在授权对话框后返回我的应用程序时,它会要求用户登录(就像他授权一样),并且在他登录后什么都不做。只是第二次代码运行,授权对话框打开,optinos“授权”& “离开App”,而不是“授权”& “不授权”/“允许”& “不要允许”。

此外,如果用户通过他在Facebook上的帐户设置删除了他的授权,而不是仅仅要求他重新授权,则会弹出一个facebook对话框(而不是帖子/授权对话框),说:“错误发生了。请稍后再试。“稍后尝试没有帮助。它会一直弹出,即使你重新启动应用程序。让它消失的唯一方法是重新安装应用程序,这将导致它重新弹出授权对话框。

所以这就是我想要实现的目标:

  1. 用户授权应用后,他不必再次登录。
  2. 在用户授权应用程序后,发布对话框将立即弹出,无需重新运行代码(通过按钮触发,顺便说一下)。
  3. 如果用户取消授权该应用,则会再次使用授权对话框提示他,而不是错误对话框
  4. 如果他拒绝授权,我将调用显示错误/等的功能
  5. 以下是相关代码:

    MyViewController.m

    - (void)shareOnFacebook
    {
        Facebook *facebook = [[Facebook alloc] initWithAppId:myAppID];
        [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] setFacebook:facebook];
        [facebook release];
        facebook = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] facebook];
        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:[NSArray arrayWithObjects:@"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
        }
    
         NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
         //Giving the dictionary some parameters for posting defaults
         [facebook dialog:@"feed" andParams:dictionary andDelegate:self]; //Note: we have 2 different delegates! appDelegate for connections & url switching, and self for dialogs
    }
    

    MyAppDelegate.h

    @interface MyAppDelegate : NSObject <UIApplicationDelegate, FBSessionDelegate, FBDialogDelegate>
    {  
        Facebook *facebook; // kept for facebook sharing, accessed only from MyViewController although delegate methods are handeled in here
    }
    @property (nonatomic, retain) Facebook *facebook;
    
    @end
    

    MyAppDelegate.m

    - (void)fbDidLogin
    {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
        [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
        [defaults synchronize];
    }
    
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
    {
        return [self.facebook handleOpenURL:url];
    }
    

    我是否可能在MyViewController上缺少几个委托函数?因为我出于某种原因看到我将其标记为实施FBDialogDelegate协议,尽管他没有实现任何功能。

    如果你们能帮助我,我会很高兴,因为这对我来说非常令人沮丧。我在互联网上找不到这个,我觉得我在这里淹死了。

    提前Tnx!

6 个答案:

答案 0 :(得分:8)

首先:

[facebook authorize:[NSArray arrayWithObjects:@"publish_stream",@"offline_access",nil] delegate:self];

此处 offline_access 键将使您的身份验证令永久 (或者更具体地说,直到用户在其应用程序中手动取消授权您的应用程序他们的Facebook帐户设置中的设置)。此外,将您的活动VC设置为委托(稍后将详细介绍)。

其次:

-(void)popUserShareFeed {
  NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  //Giving the dictionary some parameters for posting defaults
  [facebook dialog:@"feed" andParams:dictionary andDelegate:self];
}

-fbDidLogin委托方法中调用此方法(或类似方法)。如果会话仍然有效,也可以用原始方法调用它,即:

if (![facebook isSessionValid]) {
        [facebook authorize:[NSArray arrayWithObjects:@"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
} else {
  [self popUserShareFeed];
}

...以及您的新fbDidLogin

- (void)fbDidLogin
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];
    [self popUserShareFeed];
}

(注意:您必须在MyViewController.m中对其进行定义并将其用作FBSessionDelegate。它在功能上是等效的。您的AppDelegate也不需要也是您的FBSessionDelegate {1}}。

第三

实施-fbDidNotLogin:(BOOL)cancelled FBSessionDelegate方法,如下所示:

-(void)fbDidNotLogin:(BOOL)cancelled {
   if (cancelled) {
      ... some alert about the user cancelling...
   } else {
      ... some alert about how it failed for some reason...
   }
}

第四,就你的奇怪错误而言:A)Facebook SDK一般都不是很好,而且B)我只会在facebook对象上设置身份验证令牌和到期日期

A)您还没有实例化(即nil

B)您将来设置的expirationDate(即timeIntervalSinceNow [NSDate实例方法]调用它返回&gt; 0)。

答案 1 :(得分:3)

听起来您遇到了此Facebook Platform Developer forum post中描述的相同问题。我遇到了同样的问题,但在网上。在该主题中只有一个来自Facebook的回复,这是错误的信息。

Facebook拥有史上最糟糕的开发人员文档和开发人员支持,我不会屏息等待解决方案。

答案 2 :(得分:1)

我有类似但不一样的问题:消息“发生错误。请稍后再试。”总是显示出来。

问题在于没有正确配置App ID - 它是由客户提供的(所以我不确定究竟是什么问题);一切正常,因为我用我自己的测试App ID(来自之前的应用程序)替换它。

答案 3 :(得分:0)

我已经在很多应用程序中集成了FBConnect,但从未遇到过这样的关键问题。所以,你的代码中会遗漏一些东西:

检查FBAccessTokenKey&amp; FBExpirationDateKey,只需尝试使用FBConnect类的FBSession类的会话对象。

尝试使用几乎没有条件的地雷代码:

session = [[FBSession sessionForApplication:@"key" secret:@"AppSecretKey" delegate:self] retain];
        [session resume];
        _posting = YES;

        // If we're not logged in, log in first...
        if (![session isConnected]) {
            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]; // Over here posting dialog will appear , if user has already logged in or session is running.
                    }

        }
        else {
            [FBBtn setTitle:@"Login" forState:UIControlStateNormal]; // if you want to change the title of button
            [session logout];
        }

另外,请注意仅在dealloc方法中释放会话对象,而不是在任何其他方法中释放它。

 - (void)dealloc {
        [super dealloc];
        [session release];
        session = nil;
    }

希望能解决您的问题。

答案 4 :(得分:0)

不是代码问题的直接解决方案,但是......

您是否考虑过使用开源库? ShareKit就是一个很好的例子:http://getsharekit.com。集成非常简单,它可以满足您的所有需求。

答案 5 :(得分:0)

我遇到了完全相同的问题,并使用了上面的Ben Mosher的回复,但我还决定为Facebook对象创建一个简单的单例类,以便在我的AppDelegate中我可以正确处理以下函数:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

    return [[[FBManager defaultManager] facebook] handleOpenURL:url];

    //return [facebook handleOpenURL:url]; 
}

我的单身类是FBSessionDelegateFBDialogDelegate,所以它处理相应的方法。

这允许我仅在用户实际尝试发布内容时提示用户登录,而不是在应用启动时。