Facebook loginViewFetchedUserInfo вызывается дважды - программирование

Facebook loginViewFetchedUserInfo вызывается дважды

Я использую 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];

}
4b9b3361

Ответ 1

Я попробовал проект 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] &&
        ...
}

Ответ 2

У меня также была эта проблема. Мне удалось исправить это с уродливым взломом, но он работает. Я держу счетчик в делегате 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 }

Ответ 3

Исправлено в FB SDK 3.8, выпущенном 18 сентября 2013 года. Методы делегатов теперь вызывается один раз за каждый вход, независимо от того, сколько раз повторяется повторный выход из системы и обратно.


Я также смог воспроизвести это на FB SDK 3.7.1 и в своей собственной программе-образце "Scrumptious"

Как упоминалось (по крайней мере для меня), это происходит только после:

  • Вход в систему один раз
  • Выход из системы
  • Вход в систему (теперь это происходит)

Интересен порядок вызовов при повторных входах:

При первом входе в систему я я вижу следующие вызовы:

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

Ответ 4

Там может быть другая причина, с которой я столкнулся.

Моя ситуация:

  • ViewController A имеет логин (с fbloginview и его набор делегатов)
  • Пользователь решает зарегистрироваться, перемещается в ViewController B с другим fbloginview и его набором делегатов.

Вышеупомянутый огонь дважды пропускает делегат.

Я исправил это, установив делегат на nil в ViewWillDisappear в ViewController A.

-(void) viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    fbLoginButton.delegate=self;
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    fbLoginButton.delegate=nil;
}

Ответ 5

Я использовал этот простой трюк: (Определите int facebookCounter в вашем интерфейсе)

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

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

//Do stuff here

}

Ответ 6

Мне нужно было добавить безопасность потока в этот метод. Простая переменная класса не работала. Следующие два варианта будут работать в зависимости от варианта использования -

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

}

Ответ 7

только в методе loginViewFetchedUserInfo задайте делегату loginView значение nil. то его никогда нельзя назвать. и если вам нужен логин снова, установите делегат на правильный объект.