19

如 facebook-ios-sdk 的自述文件中所述,我的应用程序在执行任何 API 调用之前调用 Facebook#authorize:delegate:。

此方法要求用户进行身份验证(在 Facebook 应用程序或 Safari 中),然后将控制权交还给我的 iPhone 应用程序。问题是每次我调用该方法时它都会要求用户进行身份验证。如果他们已经授予了我的应用程序的权限,他们会收到一条消息,说明该应用程序已获得授权,他们必须按“确定”才能返回我的应用程序。看起来不是很专业。

所以我有两个问题:

  1. 用户是否总是需要重新授权才能拨打 Facebook 电话?我一直认为它会将访问令牌保存在某个地方,可能是用户默认值,这样您就不需要重新授权。

  2. 如果用户不必每次都重新授权,有没有办法检查我的应用程序是否已经获得权限,所以用户不必看到该消息并按 OK?

4

5 回答 5

23

不幸的是,Facebook SDK 没有自动为我们处理它。除了自己将其构建到 SDK 中之外,最简单的方法是:

每次分配 _facebook:

_facebook = [[Facebook alloc] initWithAppId:@"SuperDuperAppID"];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *accessToken = [prefs stringForKey:@"facebook-accessToken"];
NSString *expirationDate = [prefs stringForKey:@"facebook-expirationDate"];
_facebook.accessToken = accessToken;
_facebook.expirationDate = expirationDate;

如果您从未在 NSUserDefaults 中保存过任何内容,则将设置 nil 值。什么都没发生。否则,将设置真值,并[_facebook isSessionValid];应返回 TRUE,表示良好的值。继续进行 Facebook SDK 调用,就好像它们已登录(它们是)一样。如果为假,则调用

[facebook authorize:permissions delegate:self]; 

照常。

然后确保支持以下 Facebook 委托方法:

- (void)fbDidLogin {
NSString *accessToken = _facebook.accessToken;
NSString *expirationDate = _facebook.expirationDate;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:accessToken forKey:@"facebook-accessToken"];
[prefs expirationDate forKey:@"facebook-expirationDate"];
[prefs synchronize];
}

我在我的应用程序中使用此代码,它运行良好。我是凭记忆做到的,所以如果它不适用于复制和粘贴,我深表歉意。某处可能存在输入错误,以及内存管理不当。不要忘记访问令牌会过期,除非您获得离线许可。无论如何,上面的代码处理一切。

于 2011-04-21T19:53:13.737 回答
6

问题是每次我调用该方法时它都会要求用户进行身份验证。如果他们已经授予了我的应用程序的权限,他们会收到一条消息,说明该应用程序已获得授权,他们必须按“确定”才能返回我的应用程序。

1) 用户是否总是需要重新授权才能拨打 Facebook 电话?我一直认为它会将访问令牌保存在某个地方,可能是用户默认值,这样您就不需要重新授权。

每次都必须经过登录过程的原因是,在第一次成功登录后,Facebook SDK 并没有以持久方式保存访问令牌

2)如果用户不必每次都重新授权,有没有办法检查我的应用程序是否已经获得权限,所以用户不必看到该消息并按 OK?

Facebook SDK 不保存访问令牌的事实并不意味着您不能自己做。以下代码说明了如何从 NSUserDefaults 保存/检索访问令牌。

-(void)login {
    // on login, use the stored access token and see if it still works
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    facebook.accessToken = [defaults objectForKey:ACCESS_TOKEN_KEY];
    facebook.expirationDate = [defaults objectForKey:EXPIRATION_DATE_KEY];

    // only authorize if the access token isn't valid
    // if it *is* valid, no need to authenticate. just move on
    if (![facebook isSessionValid]) {
        NSArray * permissions = [NSArray arrayWithObjects:@"read_stream", @"offline_access", @"email", nil];
        [facebook authorize:permissions delegate:self];
    }
}

/**
 * Called when the user has logged in successfully.
 */
- (void)fbDidLogin {
    // store the access token and expiration date to the user defaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:facebook.accessToken forKey:ACCESS_TOKEN_KEY];
    [defaults setObject:facebook.expirationDate forKey:EXPIRATION_DATE_KEY];
    [defaults synchronize];
}
于 2011-04-21T20:53:25.560 回答
4

当用户登录时,您将获得一个访问令牌和一个到期日期。保存访问令牌,只要您还没有达到到期日期,就可以重复使用它。Facebook SDK 有一个方法来做这个检查: [fbConnect isSessionValid] 但它似乎有时会给出误报,所以如果请求失败,我会让用户登录。

于 2011-04-06T19:37:53.327 回答
2

1)不,我必须做Facebook *fbConnect = [[Facebook alloc] init]; [fbConnect logout:self];才能让用户会话离开

2)我想你可以打电话给accestokenFacebook.m来检查

于 2011-04-06T19:32:56.570 回答
0

这是@Daniel Amitay 答案的更实际方法:
在带有登录按钮的视图控制器中,您编写

//saving user data to user defaults in order to support Facebook SSO
let token = FBSDKAccessToken.currentAccessToken()
let prefs = NSUserDefaults.standardUserDefaults()
let nsdataToken = NSKeyedArchiver.archivedDataWithRootObject(token)
prefs.setObject(nsdataToken, forKey: "facebook-AccessToken")
prefs.synchronize()

在 AppDelegate 文件中func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool ,您编写以下内容

//restoring Facebook SSO session from user defaults
let prefs = NSUserDefaults.standardUserDefaults()
if let nsdataToken = prefs.valueForKey("facebook-AccessToken") as? NSData {
    let token = NSKeyedUnarchiver.unarchiveObjectWithData(nsdataToken) as! FBSDKAccessToken
    FBSDKAccessToken.setCurrentAccessToken(token)
}
于 2016-01-15T10:55:52.927 回答