16

我在我的应用程序中使用 facebook SDK 3.0。登录到 facebook 后,委托方法会被调用两次。

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
                            user:(id<FBGraphUser>)user {
    //loginThroughFb=TRUE;
    NSString *userId=[[NSString alloc] initWithString:[user id]];
    [self soapCallForLogin:@"" password:@"" deviceId:@"" fbid:userId];
    NSLog(@"%@",userId);
    [userId release];

}
4

7 回答 7

9

我尝试了“HelloFacebookSample”项目,该方法只调用了一次。

所以我想这种情况的最佳解决方案是保留对最后一个用户对象的引用并将其与下一次调用的新对象进行比较,如果它们相等,则可以忽略该调用。

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {
    if (![self isUser:cachedUser equalToUser:user]) {
        cachedUser = user;
        /// Do something
    }
}

- (BOOL)isUser:(id<FBGraphUser>)firstUser equalToUser:(id<FBGraphUser>)secondUser {
    return
        [firstUser.objectID isEqual:secondUser.objectID] &&
        [firstUser.name isEqual:secondUser.name] &&
        [firstUser.first_name isEqual:secondUser.first_name] &&
        [firstUser.middle_name isEqual:secondUser.middle_name] &&
        [firstUser.last_name isEqual:secondUser.last_name] &&
        ...
}
于 2013-06-18T21:06:09.333 回答
7

我也有这个问题。我设法用一个丑陋的黑客修复它,但它有效。我在 FBLoginView 委托中保留了一个计数器。当调用 fetchedUserInfo 时,我会检查计数器。如果大于零,则返回。否则,做两件事 - 1. 增加消息计数器 2. 触发延迟事件,再次将消息计数器归零。

因此,您的 fetchedUserInfo 方法将如下所示:

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
                        user:(id<FBGraphUser>)user {


       if ([self messageCounter] >0)
           return;
       else
           {
    self.messageCounter++;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
        [self setMessageCounter:0];
    });}
// Do whatever you were going to do }
于 2013-06-20T08:23:36.360 回答
5

已在 2013 年 9 月 18 日发布的FB SDK 3.8中修复。委托方法现在每次登录调用一次,无论重复注销和重新登录发生多少次。


我还能够在 FB SDK 3.7.1 和他们自己的示例程序“Scrumptious”中重现这一点

如前所述(至少对我而言),这只发生在:

  1. 登录一次
  2. 注销
  3. 重新登录(现在发生了

有趣的是重新登录时的调用顺序:

在第一次登录时,我看到的电话是:

- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView;
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;

在第二次(及以后)登录时,我看到:

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView;
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;

这为在中间方法中设置标志提供了一个方便的小解决方法,如下所示:

- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
    // Set flag
    self.isFirstLoginDone = YES;
}

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {

    // Check
    if(self.isFirstLoginDone) {
        // Execute code I want to run just once
        NSLog(@"fetched");
    }

    // Don't forget to clear the flag (I guess it shouldn't matter if everything is cleaned up)
    self.isFirstLoginDone = NO;
}
于 2013-09-14T11:45:01.877 回答
3

可能还有另一个原因,我只是面对。

我的情况:

  • ViewController A 有一个登录名(使用 fbloginview 及其委托集)
  • 用户选择注册,使用另一个 fbloginview 及其委托集移动到 ViewController B。

以上使代表两次开火。

我已通过在 ViewController A 中的 ViewWillDisappear 上将委托设置为 nil 来解决此问题。

-(void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    fbLoginButton.delegate=self;
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    fbLoginButton.delegate=nil;
}
于 2014-09-23T09:40:02.480 回答
2

我使用了这个简单的技巧:(在您的界面中定义一个 int facebookCounter)

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
                        user:(id<FBGraphUser>)user {

if (self.facebookCounter==0) {
    self.facebookCounter++;
    return;
}

//Do stuff here

}
于 2014-08-12T20:45:47.140 回答
1

我需要在这个方法中添加线程安全。一个简单的类变量不起作用。以下两个选项将起作用,具体取决于用例 -

- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {
//self.executedOnce = NO; in the init method of this class
    @synchronized(self){
         if(!self.executedOnce) {
           //do something once per init of this class
            self.executedOnce = YES;
          }
    }

//OR- This will only execute once in the lifetime of the app, thus no need for the executedOnce flag
    static dispatch_once_t onceToken;
       dispatch_once(&onceToken, ^{
            //do something once per lifetime of the app
     });

}

于 2014-12-23T21:41:08.093 回答
0

只是在 loginViewFetchedUserInfo 方法中将 loginView 的委托设置为 nil。那么它永远不能被调用。如果您需要再次登录,请将委托设置为正确的对象。

于 2015-04-08T14:18:05.110 回答