11

我正在尝试为 iOS 集成新的 Facebook SDK,但在理解某些概念时遇到了问题。

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

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

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

  4. 还有,[[FBSession activeSession] state]就是FBSessionStateCreatedTokenLoaded在这个时候。此处的教程使用isOpen调用来验证活动会话是否已加载并使用令牌打开。

那么我们调用什么来打开令牌加载会话而不将用户重定向到身份验证对话框?

提示:

FBSessionState枚举中,因为FBSessionStateOpen它说:

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

然而FBSessionStateCreatedTokenLoaded被描述为:

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

你能帮我弄清楚这些会话转换吗?

4

5 回答 5

31

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

下面的代码也可以通过这个gist获得。

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

其他人提到的要注意的关键是,有时您有一个无法立即使用的缓存授权令牌,但如果您对其进行 Facebookopen调用,则可以使其可重用(刷新)。这个开放的调用在幕后工作,不会触发任何 UI/不和谐的 OAuth 窗口/应用程序切换(如果您有缓存的令牌)。

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

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

关于这门课的其他花絮:

  • 我这里有一个属性来缓存登录用户,类型符合协议FBGraphUser。但是,这里演示的任何登录方法都没有使用它。
  • 适用于 iOS 的 Facebook SDK 3.0 示例代码建议构建您自己的类来保持和管理这些类型的操作,如果您的应用程序不仅仅是一个微不足道的应用程序。下面的这门课是我的应用程序这个想法的开始。
  • 你可以用 NSLog 替换我的 'log4Info' 和 'log4Debug' 宏来让它工作。
#import "UWFacebookService.h"

@implementation UWFacebookService

// 静止的
静态常量 int ddLogLevel = LOG_LEVEL_DEBUG;

// 强的
@synthesize facebookGraphUser = _facebookGraphUser;


#pragma mark - 查询

- (BOOL)isSessionStateEffectivelyLoggedIn:(FBSessionState)state {
    BOOL 有效登录;

    开关(状态){
        案例 FBSessionStateOpen:
            log4Info(@"Facebook 会话状态:FBSessionStateOpen");
            有效LoggedIn = YES;
            休息;
        案例 FBSessionStateCreatedTokenLoaded:
            log4Info(@"Facebook 会话状态:FBSessionStateCreatedTokenLoaded");
            有效LoggedIn = YES;
            休息;
        案例 FBSessionStateOpenTokenExtended:
            log4Info(@"Facebook 会话状态:FBSessionStateOpenTokenExtended");
            有效LoggedIn = YES;
            休息;
        默认:
            log4Info(@"Facebook 会话状态:不是打开或可打开类型之一。");
            有效登录 = 否;
            休息;
    }

    返回有效登录;
}

/**
* 确定 Facebook 会话是否具有授权状态。如果它是缓存的,它可能仍需要打开
* 令牌,但此调用的目的是确定用户是否至少被授权
* 明确询问任何事情。
*/
- (BOOL)isLoggedIn {
    FBSession *activeSession = [FBSession activeSession];
    FBSessionState state = activeSession.state;
    BOOL isLoggedIn = activeSession && [self isSessionStateEffectivelyLoggedIn:state];

    log4Info(@"Facebook 活动会话状态:%d;登录结论:%@", state, (isLoggedIn ?@"YES" : @"NO"));

    返回是登录;
}


/**
* 如果我们加载了有效令牌(可能需要后台刷新),则尝试静默打开 Facebook 会话。
* 在那次尝试之后,我们遵循会话处于有效授权状态之一的基本概念。
*/
- (BOOL)isLoggedInAfterOpenAttempt {
    log4Debug(@"FBSession.activeSession: %@", FBSession.activeSession);

    // 如果我们没有缓存的令牌,在此处调用 open 将导致 UX 登录
    // 发生; 我们不希望这种情况发生,除非用户点击设置中的登录按钮,所以
    // 我们在这里检查以确保在调用 open 之前我们有一个令牌
    如果(FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded){
        log4Info(@"我们有一个缓存的令牌,所以我们要为用户重新建立登录。");
        // 即使我们有一个缓存的令牌,我们也需要登录才能使会话可用:
        [FBSession.activeSession openWithCompletionHandler:^(FBSession *session, FBSessionState 状态, NSError *error) {
            log4Info(@"已完成打开登录会话,状态:%d", status);
        }];
    }
    别的 {
        log4Info(@"活动会话不在状态'FBSessionStateCreatedTokenLoaded'。它有状态:%d", FBSession.activeSession.state);
    }

    返回 [self isLoggedIn];
}

@结尾

于 2012-08-30T16:55:44.877 回答
5

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

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

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

之所以这样设计,是因为如果令牌可用但已过期,Facebook 库会告诉您 - “嘿,令牌已过期,除非您现在获得新令牌,否则请考虑您已注销。”

希望有帮助。

于 2012-08-12T01:07:20.933 回答
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
    }];
}
于 2012-08-12T00:44:03.310 回答
1

这可能是一个旧线程,但现在您所要做的就是在您的应用程序委托中的 (void)applicationDidBecomeActive:(UIApplication *)application 中调用您的 FBSession 对象中的 handleDidBecomeActive。

例如:

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

MLFacebook 是我的 FBSession 对象。

于 2013-05-26T06:28:04.347 回答
0

只需调用您的初始化视图控制器

self.FBloginView = [[FBLoginView alloc] init];
于 2014-04-12T22:03:01.153 回答