Facebook loginViewFetchedUserInfo被调用两次

时间:2012-10-31 11:35:41

标签: iphone ios facebook-graph-api facebook-ios-sdk

我在我的应用中使用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];

}

7 个答案:

答案 0 :(得分: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] &&
        ...
}

答案 1 :(得分: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 }

答案 2 :(得分:5)

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


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

如上所述(至少对我来说),这只发生在:

之后
  1. 登录一次
  2. 退出
  3. 重新登录(现在发生
  4. 有趣的是重新登录时调用的顺序:

    首次登录时,我看到的是:

    - (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;
    }
    

答案 3 :(得分: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;
}

答案 4 :(得分:2)

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

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

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

//Do stuff here

}

答案 5 :(得分: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
     });

}

答案 6 :(得分:0)

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