2012-08-09 5 views
11

Sto cercando di integrare il nuovo SDK di Facebook per iOS e ho riscontrato un problema nella comprensione di alcuni concetti.Apertura di FBSession in lanci consecutivi (SDK FB per SDK 3.0)

  1. ho l'autenticazione tramite [FBSession sessionOpenWithPermissions:...] finestra di autenticazione viene in su e torno l'applicazione. Autori successo.

  2. Quindi chiudere l'app, riavviare di nuovo. [[FBSession activeSession] accessToken] restituisce correttamente il token precedentemente salvato.

  3. Tuttavia, allo stesso tempo, [[FBSession activeSession] isOpen] restituisce NO. (Questo significa che la sessione non è pronta per l'uso.)

  4. Inoltre, [[FBSession activeSession] state] è FBSessionStateCreatedTokenLoaded in questo momento. Il tutorial here utilizza la chiamata isOpen per verificare che la sessione attiva sia caricata e aperta con il token.

Quindi, come chiamiamo per aprire la sessione con token senza reindirizzare l'utente alla finestra di autenticazione?

Suggerimenti:

In FBSessionState enum, per FBSessionStateOpen si dice:

Aprire lo stato della sessione utente che indica è connesso o un token memorizzato nella cache è disponibile.

Tuttavia FBSessionStateCreatedTokenLoaded è descritto come:

Uno dei due stati di sessione iniziali che indicano che un token memorizzato nella cache è stato caricato; quando una sessione è in questo stato, una chiamata per aprire * si tradurrà in una sessione aperta, senza UX o app-switching

La prego di aiutarmi a capire la comprensione di queste transizioni di sessione?

+0

Bisogna riaprire la sessione su ogni lancio app. –

+2

Come si fa? Mi manca quella parte. sarebbe '[FBSession sessionOpenWithPermissions: ...]' a fare il trucco senza mostrare la finestra di autenticazione ogni volta? –

+2

questo: '+ (BOOL) openActiveSessionWithAllowLoginUI: (BOOL) allowLoginUI' e anche Google FBSession - letteralmente il primo hit. –

risposta

31

Includo una classe di utilità di Facebook che ho scritto che aiuta a capire lo stato di accesso, perché esporre un messaggio "connesso"/"non connesso" all'utente nella mia propria UI Impostazioni, oltre a utilizzare il componente "FBLoginView" effettivo quando arriva il momento di consentire all'utente di passare dallo stato di autorizzazione.

Il codice seguente è disponibile anche tramite questo gist.

Probabilmente non ho interpretato correttamente tutti i tipi FBSessionState nella mia istruzione switch, ma finora mi è servito bene nei casi che ho testato (l'ho appena messo insieme).

La cosa fondamentale da notare, a cui altri hanno fatto riferimento, è che a volte si dispone di un token di autorizzazione memorizzato nella cache che non è possibile utilizzare immediatamente, ma se si effettua una chiamata su Facebook open, è possibile ottenerlo riutilizzabile (aggiornato). Questa chiamata aperta funziona dietro le quinte, senza attivare alcuna commutazione di finestra/app OIuth/ostruzione dell'interfaccia utente (se si dispone di un token memorizzato nella cache).

Vedere i miei commenti nel metodo isLoggedInAfterOpenAttempt. Nota come controllo lo stato da FBSessionStateCreatedTokenLoaded e solo dopo, effettua la chiamata a

-openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error).

Altre curiosità su questa classe:

  • mi hanno una proprietà qui per memorizzare nella cache l'utente collegato, di tipo conforme al protocollo FBGraphUser. Tuttavia, non è utilizzato in nessuno dei metodi di accesso qui dimostrati.
  • Il codice di esempio di Facebook SDK 3.0 per iOS suggerisce di costruire la propria classe per conservare e gestire questo tipo di operazioni, se si dispone di qualcosa di più di un'app banale. Questa classe di seguito è l'inizio di questa idea per la mia app.
  • È possibile sostituire le mie macro 'log4Info' e 'log4Debug' con NSLog per farlo funzionare.
 
#import "UWFacebookService.h" 

@implementation UWFacebookService 

// Static 
static const int ddLogLevel = LOG_LEVEL_DEBUG; 

// Strong 
@synthesize facebookGraphUser = _facebookGraphUser; 


#pragma mark - Inquiries 

- (BOOL)isSessionStateEffectivelyLoggedIn:(FBSessionState)state { 
    BOOL effectivelyLoggedIn; 

    switch (state) { 
     case FBSessionStateOpen: 
      log4Info(@"Facebook session state: FBSessionStateOpen"); 
      effectivelyLoggedIn = YES; 
      break; 
     case FBSessionStateCreatedTokenLoaded: 
      log4Info(@"Facebook session state: FBSessionStateCreatedTokenLoaded"); 
      effectivelyLoggedIn = YES; 
      break; 
     case FBSessionStateOpenTokenExtended: 
      log4Info(@"Facebook session state: FBSessionStateOpenTokenExtended"); 
      effectivelyLoggedIn = YES; 
      break; 
     default: 
      log4Info(@"Facebook session state: not of one of the open or openable types."); 
      effectivelyLoggedIn = NO; 
      break; 
    } 

    return effectivelyLoggedIn; 
} 

/** 
* Determines if the Facebook session has an authorized state. It might still need to be opened if it is a cached 
* token, but the purpose of this call is to determine if the user is authorized at least that they will not be 
* explicitly asked anything. 
*/ 
- (BOOL)isLoggedIn { 
    FBSession *activeSession = [FBSession activeSession]; 
    FBSessionState state = activeSession.state; 
    BOOL isLoggedIn = activeSession && [self isSessionStateEffectivelyLoggedIn:state]; 

    log4Info(@"Facebook active session state: %d; logged in conclusion: %@", state, (isLoggedIn ? @"YES" : @"NO")); 

    return isLoggedIn; 
} 


/** 
* Attempts to silently open the Facebook session if we have a valid token loaded (that perhaps needs a behind the scenes refresh). 
* After that attempt, we defer to the basic concept of the session being in one of the valid authorized states. 
*/ 
- (BOOL)isLoggedInAfterOpenAttempt { 
    log4Debug(@"FBSession.activeSession: %@", FBSession.activeSession); 

    // If we don't have a cached token, a call to open here would cause UX for login to 
    // occur; we don't want that to happen unless the user clicks the login button over in Settings, and so 
    // we check here to make sure we have a token before calling open 
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) { 
     log4Info(@"We have a cached token, so we're going to re-establish the login for the user."); 
     // Even though we had a cached token, we need to login to make the session usable: 
     [FBSession.activeSession openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) { 
      log4Info(@"Finished opening login session, with state: %d", status); 
     }]; 
    } 
    else { 
     log4Info(@"Active session wasn't in state 'FBSessionStateCreatedTokenLoaded'. It has state: %d", FBSession.activeSession.state); 
    } 

    return [self isLoggedIn]; 
} 

@end 

2

Prova di codice seguente:

///////////////////////////////// 

-(void)CallBackOpenURLFromDelegate:(NSURL *)url 
{ 
    [FBSession.activeSession handleOpenURL:url]; 
} 

-(id)init 
{ 
    self = [super init]; 
    FBSessionTokenCachingStrategy* pToken = [[[FBSessionTokenCachingStrategy alloc]initWithUserDefaultTokenInformationKeyName:@"STokenInfoX"]autorelease]; 
    FBSession.activeSession = [[FBSession alloc] initWithAppID:FACEBOOK_AppId 
                permissions:[NSArray arrayWithObject:@"status_update"] 
               urlSchemeSuffix:@"" 
              tokenCacheStrategy: pToken]; 
    return self; 
} 


-(void)dealloc 
{ 
    [FBSession.activeSession close]; 
    [super dealloc]; 
} 

-(void) UploadImpl:(NSString*)strImagePath 
{ 
    FBRequest *photoUploadRequest = [FBRequest requestForUploadPhoto: [UIImage imageWithContentsOfFile:strImagePath ]]; 
    [photoUploadRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) 
    { 
     NSLog(@"%@",[error description]); 
     //self.delegate 
    }]; 
} 
5

Ciò significa che quando si dispone di un gettone salvato (cache) o comunque già disponibili, la libreria di Facebook per iOS si richiede ancora di utilizzare il metodo aperto per reinizializzare una sessione.

Facendolo, se è possibile riutilizzare un token esistente (e questo è il tuo caso), e in questo caso l'UX (user experience, ovvero commutazione dell'app o popup di accesso Facebook) non verrà attivato.

L'impressione dell'utente è che non si sia mai disconnesso, ma nell'app ciò che sta accadendo è che si sta contattando Facebook per riaprire una sessione.

La ragione per questo è stato progettato come tale è perché nel caso in cui il token è disponibile, ma scaduto, la biblioteca di Facebook vi dirà - "Ehi pegno scaduto, consideratevi registrato a meno che si ottiene un nuovo token ora"

Spero che questo aiuti.

1

questo può essere un vecchio thread, ma ora un giorno tutto quello che dovete fare è chiamare handleDidBecomeActive nell'oggetto FBSession dall'interno (void) applicationDidBecomeActive: (UIApplication *) applicazione nella vostra applicazione delegato.

Ad esempio:

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    [[[MLSocialNetworksManager sharedManager] MLFacebook] handleDidBecomeActive]; 
} 

Dove MLFacebook è il mio oggetto FBSession.

+0

Perché hai creato un'altra classe chiamata MLFacebook? 'HandleDidBecomeActive' è un metodo di' FBSession'? –

+0

Sta incapsulando la mia logica di Facebook. In nessun modo è richiesto. –

0

semplicemente chiamare nel vostro init View Controller

self.FBloginView = [[FBLoginView alloc] init];