2012-10-31 13 views
16

Używam Facebook SDK 3.0 w mojej aplikacji. Metoda delegatów jest wywoływana dwukrotnie, gdy po zalogowaniu się na facebooku.Facebook loginViewFetchedUserInfo jest wywoływana dwukrotnie

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

} 
+0

Zdarza się również dla mnie na Facebook SDK 3.7.0. Delegat jest wywoływany tylko raz przy pierwszym logowaniu i dwa razy (przez tę samą, nową instancję) we wszystkich kolejnych próbach zalogowania. – owenfi

+0

To jest nadal zepsute w Facebook SDK 3.11 – jstricker

+0

Jestem taki sam z tobą @jstricker, z FB DSK v3.11.1. – wagyaoo

Odpowiedz

9

Próbowałem projektu "HelloFacebookSample" i metoda jest wywoływana tylko raz.

Sądzę więc, że najlepszym rozwiązaniem dla takiego przypadku jest zachowanie odniesienia do ostatniego obiektu użytkownika i porównanie go z nowym obiektem, z którego otrzymasz następne połączenie, a jeśli jest to równe możesz po prostu zignorować to połączenie .

- (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] && 
     ... 
} 
7

Też miałem ten problem. Udało mi się to naprawić brzydkim hackerem, ale działa. Utrzymuję licznik w delegacie FBLoginView. Kiedy wywoływanaUserInfo jest wywoływana, sprawdzam licznik. Jeśli jest większy od zera, wróć. W przeciwnym razie wykonaj dwie czynności - 1. Zwiększ licznik wiadomości 2. Uruchomienie opóźnionego zdarzenia, które ponownie zeruje licznik wiadomości.

Więc metoda fetchedUserInfo będzie wyglądać następująco:

- (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 } 
+1

Sprytniejszym sposobem byłoby po prostu umieszczenie go w bloku 'dispatch_once', aby zapewnić, że jest on tylko raz wywoływany. Jeśli chcesz, aby był wywoływany raz na instancję, możesz w tym celu utworzyć właściwość 'dispatch_once_t' w klasie. – iwasrobbed

+0

Dobra uwaga! Dzięki! – gillyD

5

Poprawiono w FB SDK 3.8 wydany 18 września 2013. Metody delegat obecnie nazywa raz logowania, niezależnie od tego, ile razy powtarzane zalogowaniu się iz powrotem pojawić się.


Byłem również w stanie odtworzyć to na FB SDK 3.7.1 i we własnym przykładzie programu "Scrumptious"

Jak wspomniano (przynajmniej dla mnie), dzieje się tak dopiero po:

  1. Logowanie raz
  2. Wylogowanie
  3. ponowne zalogowanie (Teraz zdarza)

Co ciekawe kolejność rozmów w sprawie ponownego logowania:

Na pierwszym logowaniu I zaproszeń widzę to:

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

dniu 2 (i później) loginy widzę :

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

co daje mało poręczne obejście ustawiania flagi w metodzie środkowej tak:

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

Złożyłem fb błąd tutaj: https://developers.facebook.com/bugs/1414348378783720 i został ustawiony na niski priorytet i "przypisany". – owenfi

+0

3.8 .. ?? Najnowsza wersja od tego czasu to 3.15 – shashwat

+0

@shashwat Najwyraźniej została ponownie wprowadzona w wersji 3.11 (patrz wątek komentarza w linku do raportu o błędzie) – owenfi

2

użyłem tego prosty trik: (Definiowanie int facebookCounter w interfejsie)

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

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

//Do stuff here 

} 
3

Nie może być inny powód, który ja jsut czynienia.

Moja sytuacja:

  • ViewController A ma logowanie (z fbloginview i jego zestaw delegata)
  • Użytkownik zdecyduje się zarejestrować, przenosi się do ViewController B z innym fbloginview i jego zestaw delegata.

Powyższe powoduje, że delegat strzela dwa razy.

Mam ustalony przez ustawienie delegata do zera na ViewWillDisappear w ViewController A.

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

w tej samej sytuacji, ale to nie działa dla mnie – DaynaJuliana

1

Musiałem dodać bezpieczeństwa wątku w tej metodzie. Prosta zmienna klasy nie działa. Poniższe dwie opcje będą działać, w zależności od zastosowania CASE-

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

}

0

tylko w sposób loginViewFetchedUserInfo ustawiony delegata LoginView do zera. to nigdy nie można go nazwać. i jeśli potrzebujesz loginu ponownie, ustaw delegata na poprawny obiekt.

Powiązane problemy