连续启动时打开FBSession(适用于SDK 3.0的FB SDK)

时间:2012-08-09 20:57:15

标签: ios facebook facebook-ios-sdk

我正在尝试整合适用于iOS的新Facebook SDK,并且在理解某些概念时遇到了问题。

  1. 我使用[FBSession sessionOpenWithPermissions:...]验证身份验证对话框出现并返回应用程序。验证成功。

  2. 然后关闭应用,重新启动。 [[FBSession activeSession] accessToken]成功返回以前保存的令牌。

  3. 但是,与此同时,[[FBSession activeSession] isOpen]会返回NO。 (这意味着会话尚未准备好使用。)

  4. 此时,[[FBSession activeSession] state]目前为FBSessionStateCreatedTokenLoaded。教程here使用isOpen调用来验证活动会话是否已加载并使用令牌打开。

  5. 那么我们打算如何在不将用户重定向到auth对话框的情况下打开加载令牌的会话?

    提示:

    FBSessionState枚举中,对于FBSessionStateOpen,它说:

      

    打开会话状态,指示用户已登录或缓存令牌可用。

    但是FBSessionStateCreatedTokenLoaded被描述为:

      

    两个初始会话状态之一,表示已加载缓存的令牌;当会话处于此状态时,调用open *将导致打开会话,而无需UX或应用程序切换

    你能帮我理解这些会话过渡吗?

5 个答案:

答案 0 :(得分:31)

我包含了一个我编写的Facebook实用程序类,它有助于理解登录状态,因为我在自己的设置UI中向用户公开了“登录”/“未登录”消息,此外还使用了实际的当允许用户切换授权状态时,'FBLoginView'组件。

以下代码也可通过此gist

获取

我可能没有在我的switch语句中正确解释所有FBSessionState类型,但到目前为止,在我测试过的情况下它很适合我(我只是将它们放在一起)。

其他人提到的关键是,有时候你有一个你不能立即使用的缓存授权令牌,但如果你对它进行了一次Facebook open调用,你可以获得它可以重复使用(刷新)。此公开调用在幕后工作,不会触发任何UI / jarring OAuth窗口/应用切换(如果您有缓存的令牌)。

在方法isLoggedInAfterOpenAttempt中查看我的评论。请注意我如何检查状态为FBSessionStateCreatedTokenLoaded,然后才调用

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

关于这个课程的其他花絮:

  • 我在这里有一个属性来缓存登录用户,其类型符合协议FBGraphUser。但是,它并未在此处演示的任何登录方法中使用。
  • Facebook SDK 3.0 for iOS示例代码建议构建自己的类来保持和管理这些类型的操作,如果你有一个简单的应用程序。下面我的这个类是我的应用程序的想法的开始。
  • 您可以将我的'log4Info'和'log4Debug'宏替换为NSLog,以使其正常工作。
#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

答案 1 :(得分:5)

这意味着当您有令牌保存(缓存)或已经可用时,Facebook iOS库仍然要求您使用open方法重新初始化会话。

如果可以重复使用现有令牌(这是您的情况),那么这样做将会触发UX(用户体验 - 即应用切换或Facebook登录弹出窗口)。

用户的印象是他从未退出,但在应用程序中发生的事情是您正在联系Facebook以重新开启会话。

这样设计的原因是因为在令牌可用但已过期的情况下,Facebook库会告诉您 - “嘿令牌已过期,请考虑自己退出,除非您现在获得新令牌。”

希望有所帮助。

答案 2 :(得分:2)

尝试以下代码示例:

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

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

答案 3 :(得分:1)

这可能是一个旧线程,但现在你需要做的就是在你的应用代理中的(void)applicationDidBecomeActive:(UIApplication *)应用程序中调用fBSession对象中的handleDidBecomeActive。

例如:

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

MLFacebook是我的FBSession对象。

答案 4 :(得分:0)

只需调用初始视图控制器

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