2012-10-11 12 views
10

Voglio mettere qualche integrazione Facebook nella mia app. A questo punto sono riuscito ad accedere, postare al muro di amici, recuperare la lista di amici, ecc. Tutto è OK tranne una cosa ...Facebook SDK 3.1 iOS: gestisci il login se l'utente rimuove l'app da Impostazioni Facebook

Se l'utente rimuove l'app da your Facebook settings/Applications e quindi entra in l'app per iOS, il codice non riconosce che l'app di Facebook è stata rimossa dalle impostazioni utente e presuppone che abbia effettuato l'accesso (questo è il problema perché se l'utente tenta di postare sulla bacheca di un amico, l'app non fa nulla).

Quindi, l'utente chiude l'applicazione iOS e rilancia lo ... Con questo rilancio, l'applicazione iOS "è fisso" e rileva che l'utente non è più connesso.

io non riesco a rilevare il momento giusto dopo che l'utente elimina l'applicazione Facebook dalle impostazioni al fine di portare il flusso di accesso per l'utente ...

Ecco il mio codice:

alla prima scena del mio app ...

if([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded) 
{ 
    NSLog(@"Logged in to Facebook"); 
    [self openFacebookSession]; 
    UIAlertView *alertDialog; 

    alertDialog = [[UIAlertView alloc] initWithTitle:@"Facebook" message:@"You're already logged in to Facebook" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil]; 

    [alertDialog show]; 

    [alertDialog release]; 
    return YES; 
} 
else{ 
    NSLog(@"Not logged in to Facebook"); //Show the login flow 
    return NO; 
} 

Qui è il codice per openFacebookSession

-(void)openFacebookSession 
{ 
    NSArray *permissions = [[NSArray alloc] initWithObjects: 
          @"publish_stream", 
          nil]; 

    [FBSession openActiveSessionWithPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) { 
     [self sessionStateChanged:session state:status error:error]; 
    }]; 
} 

Codice in sessionStateChanged ...

-(void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error 
{ 
    switch (state) { 
     case FBSessionStateOpen: { 
      NSLog(@"Session opened"); 
     } 
      break; 
     case FBSessionStateClosed: 
     case FBSessionStateClosedLoginFailed: 
      [FBSession.activeSession closeAndClearTokenInformation]; 
      break; 
     default: 
      break; 
    } 

    if (error) { 
     UIAlertView *alertView = [[UIAlertView alloc] 
            initWithTitle:@"Error" 
            message:error.localizedDescription 
            delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil]; 
     [alertView show]; 
    } 
} 

Grazie mille!

+0

Come hai risolto questo problema? – SAHM

+0

Non l'ho ancora risolto ...: C – Axort

+0

Questa risposta mi ha aiutato http://stackoverflow.com/questions/12745235/handle-invalid-accesstoken-with-fbsession-openactivesessionwithreadpermissions-i – michael23

risposta

0

Ho lo stesso problema e non ho potuto trovare la documentazione adeguata sui codici di errore sul sito di Facebook SDK.

Ho risolto il problema confrontando il valore [error code]; o [error userInfo];.

La sessione avrà lo stato FBSessionStateClosedLoginFailed e dizionario userInfo dell'errore avrà la seguente forma

"com.facebook.sdk:ErrorLoginFailedReason" = "com.facebook.sdk:ErrorLoginFailedReason"; 

D'altro codice di errore invece mi mostra 2 in modo che si può gestire a fine sessionStateChanged :: : la funzione

- (void)sessionStateChanged:(FBSession *)session 
        state:(FBSessionState)state 
        error:(NSError *)error { 
switch (state) { 
    case FBSessionStateOpen: { 
     //update permissionsArrat 
     [self retrieveUSerPermissions]; 

     if (!needstoReopenOldSession) { 
      //First User information 
      [self getUserInformation:nil]; 
     } 

     NSNotification *authorizationNotification = [NSNotification notificationWithName:facebookAuthorizationNotification object:nil]; 
     [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification]; 

    } 
    case FBSessionStateClosed: { 
     break; 
    } 
    case FBSessionStateClosedLoginFailed: { 
     [FBSession.activeSession closeAndClearTokenInformation]; 
     break; 
    } 
    default: 
     break; 
} 

if (error) 
{ 
    NSNotification *authorizationNotification = [NSNotification notificationWithName:faceBookErrorOccuredNotification object:error]; 
    [[NSNotificationCenter defaultCenter] postNotification:authorizationNotification]; 
} 
} 
+0

Salve! Grazie per la tua risposta ... In realtà, l'errore del metodo sessionStateChanged è sempre nullo. Non so perché: C. – Axort

+0

se l'errore è nullo non può essere il caso FBSessionStateClosedLoginFailed –

+0

Che cosa è retrieveUSerPermissions? – Dejell

3

in realtà è molto difficile da analizzare fuori e rilevare questi tipi di errori per due motivi:

  1. io non riesco a capire un modo per rilevare questo problema fino a quando effettivamente tenta e fallisce un FBRequest (o simile), e
  2. L'oggetto NSError passato dal fallito FBRequest è assurdamente difficile da analizzare e utilizzare in alcun modo funzionale.

Di seguito è il metodo pazzo che ho scritto mentre letteralmente tirando una notte prima di affrontare questo. Gestisce l'oggetto NSError *error dal tentativo fallito FBRequest e lo passa ai metodi rilevanti OPPURE visualizza l'errore più sensibile che ho trovato (o che colpisce il punto di accesso inferiore).

Nota i commenti, in particolare intorno a innerError e parsedResponse, quel dettaglio che ho scoperto fino ad ora. Buona fortuna, soldato coraggioso:

- (void)handleFacebookError:(NSError *)error 
     withPermissionType:(RMFacebookPermissionsType)type // this is just a typedef enum specifying Write or Read permissions so I can react accordingly 
      withCompletion:(void (^)(BOOL retry))completionBlock { 

    newMethodDebugLog; 
    NSParameterAssert(error); 
    NSParameterAssert(type); 
    NSParameterAssert(completionBlock); // the completion block tells the controller whether the error is 'fatal' or can be recovered - if YES, it can be recovered 

    // this is the parsed result of the graph call; some errors can appear here, too, sadly 
    NSDictionary *parsedResponse = [error.userInfo objectForKey:@"com.facebook.sdk:ParsedJSONResponseKey"]; 
    int parsedErrorCode = [[[[parsedResponse objectForKey:@"body"] 
          objectForKey:@"error"] 
          objectForKey:@"code"] 
          intValue]; 

    // this is an instance of NSError created by Facebook; it contains details about the error 
    NSError *innerError = [error.userInfo objectForKey:@"com.facebook.sdk:ErrorInnerErrorKey"]; 

    // innerError is usually un-recoverable 
    if (innerError) { 

     // innerError seems to be the response given in true HTTP problems; 
     DebugLog(@"______innerError FOUND______"); 
     DebugLog(@"innerError: %@",innerError); 
     DebugLog(@"innerError.code: %d",innerError.code); 

     // digging deep enough, you can actually find a coherent error message! :D 
     DebugLog(@"innerError.localizedDescription: %@",innerError.localizedDescription); 

     if (![alert isVisible]) { 

      NSString *errorString = @"Facebook Connection Failed"; 

      NSString *okString = @"OK"; 

      alert = [[UIAlertView alloc] initWithTitle:errorString 
               message:innerError.localizedDescription 
               delegate:nil 
            cancelButtonTitle:okString 
            otherButtonTitles:nil]; 

      [alert show]; 

     } else { 

      DebugLog(@"Alert already showing!"); 

     } 

     completionBlock(NO); 

    } else if (parsedResponse && 
       parsedErrorCode != 2) { // I honestly forget what error 2 is.. documentation fail :(

     // parsedResponses can usually be recovered 
     DebugLog(@"parsed response values: %@",[parsedResponse allValues]); 

     switch (parsedErrorCode) { 
      case 2500: 
      case 200: 
      case 190: 
      { 
       DebugLog(@"parsedError code hit! forcing re-login."); 

       // all errors in case 190 seem to be OAuth issues 
       // http://fbdevwiki.com/wiki/Error_codes#Parameter_Errors 
       // if needed, "error_subcode" 458 == user has de-authorized your app 
       // case 2500 reported while grabbing from a photo album & not logged in 
       // case 200 "requires extended permission: publish_actions" 

       if (type == RMFacebookPermissionsTypeRead) { 

        [self _getFacebookReadPermissionsWithUI:YES 
               completion:completionBlock]; 

       } else if (type == RMFacebookPermissionsTypeWrite) { 

        [self _getFacebookWritePermissionsWithUI:YES 
                completion:completionBlock]; 

       } 

       break; 
      } 

      default: 
       completionBlock(YES); 
       break; 
     } 

    } else { 

     if (![alert isVisible]) { 

      NSString *errorString = @"Facebook Error"; 

      NSString *messageString = @"Mixture Photos was unable to connect to Facebook on your behalf. This is usually a temporary problem. Please try again later."; 

      NSString *okString = @"OK"; 

      alert = [[UIAlertView alloc] initWithTitle:errorString 
               message:messageString 
               delegate:nil 
            cancelButtonTitle:okString 
            otherButtonTitles:nil]; 

      [alert show]; 

     } else { 

      DebugLog(@"Alert already showing!"); 

     } 

     completionBlock(NO); 

    } 
} 
5

ho trovato questo accada a me stesso .... E 'stato scoperto quando un utente ha cambiato la loro password di facebook, e noi non poteva più autenticarsi. Effettuando una risincronizzazione manuale/cancellazione della sessione dell'account, è stato consentito loro di accedere nuovamente.

-(void)syncFacebookAccount 
{ 
    [self forceLogout]; 
    ACAccountStore *accountStore = [[ACAccountStore alloc] init]; 
    ACAccountType *accountTypeFB = [accountStore   accountTypeWithAccountTypeIdentifier:@"com.apple.facebook"]; 
    if (accountStore && accountTypeFB) { 
    NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB]; 
    id account; 
    if (fbAccounts && [fbAccounts count] > 0 && (account = [fbAccounts objectAtIndex:0])) { 
    [accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) { 
        // Not actually using the completion handler... 
    }]; 
      } 
     } 
    } 
Problemi correlati