我正在尝试整合适用于iOS的新Facebook SDK,并且在理解某些概念时遇到了问题。
我使用[FBSession sessionOpenWithPermissions:...]
验证身份验证对话框出现并返回应用程序。验证成功。
然后关闭应用,重新启动。 [[FBSession activeSession] accessToken]
成功返回以前保存的令牌。
但是,与此同时,[[FBSession activeSession] isOpen]
会返回NO
。 (这意味着会话尚未准备好使用。)
此时,[[FBSession activeSession] state]
目前为FBSessionStateCreatedTokenLoaded
。教程here使用isOpen
调用来验证活动会话是否已加载并使用令牌打开。
那么我们打算如何在不将用户重定向到auth对话框的情况下打开加载令牌的会话?
提示:
在FBSessionState
枚举中,对于FBSessionStateOpen
,它说:
打开会话状态,指示用户已登录或缓存令牌可用。
但是FBSessionStateCreatedTokenLoaded
被描述为:
两个初始会话状态之一,表示已加载缓存的令牌;当会话处于此状态时,调用open *将导致打开会话,而无需UX或应用程序切换
你能帮我理解这些会话过渡吗?
答案 0 :(得分:31)
我包含了一个我编写的Facebook实用程序类,它有助于理解登录状态,因为我在自己的设置UI中向用户公开了“登录”/“未登录”消息,此外还使用了实际的当允许用户切换授权状态时,'FBLoginView'组件。
以下代码也可通过此gist。
获取我可能没有在我的switch语句中正确解释所有FBSessionState
类型,但到目前为止,在我测试过的情况下它很适合我(我只是将它们放在一起)。
其他人提到的关键是,有时候你有一个你不能立即使用的缓存授权令牌,但如果你对它进行了一次Facebook open
调用,你可以获得它可以重复使用(刷新)。此公开调用在幕后工作,不会触发任何UI / jarring OAuth窗口/应用切换(如果您有缓存的令牌)。
在方法isLoggedInAfterOpenAttempt
中查看我的评论。请注意我如何检查状态为FBSessionStateCreatedTokenLoaded
,然后才调用
-openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error)
。
关于这个课程的其他花絮:
FBGraphUser
。但是,它并未在此处演示的任何登录方法中使用。#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];