我在将 Facebook 集成到我的 iOS 应用程序中时遇到问题。当我启动我的应用程序时,它会重定向到 Facebook 应用程序,这很好。但身份验证对话框只是从屏幕上消失(就像取消的模态视图控制器一样),委托方法没有触发,我留在 Facebook 应用程序中,而不是被重定向回我的应用程序。我显然没有成功初始化会话。我按照iOS教程中的步骤进行操作,但我一定是在某个地方出错了。我见过的大多数问题都是关于错误或试图从身份验证对话框中获得不同的行为。如果这是一个骗局,请引导我回答同样的问题,因为我在这里碰壁了。我已经按照教程中的说明设置了 .plist。我使用了从 iTunes connect 获取的应用程序包标识符。我的常量 kAppID 是我从 Facebook Developer 应用程序界面获取的 AppID。阅读了 FB 静态库的标头和实现文件,以及 FB 的文档和教程后,在我看来,如果我想做的就是重定向到 FB 应用程序,登录,然后重定向回我自己的应用程序,这些步骤加上下面的代码应该足够了。
在 AppDelegate.m 中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
kAppID = @"(this is where my app ID is)";
// Override point for customization after application launch.
facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:self];
[facebook setSessionDelegate:self];
return YES;
}
在 ViewController.m 中,我获取对 Facebook 的同一实例的引用,然后调用以下命令:
- (void)loginToFacebook:(id)sender {
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
}
是否有一些我不知道的问题?或者也许我错过了关键的一步?
哦,顺便说一句,Xcode 4.3.1、ios5SDK、iPhone 4S、ARC。
.plist 的 SS。
AppDelegate.h:
#import <UIKit/UIKit.h>
#import "Facebook.h"
#import "FBConnect.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate> {
Facebook *facebook;
NSUserDefaults *defaults;
NSString *kAppID;
}
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) Facebook *facebook;
@property (strong, nonatomic) id delegate;
@end
AppDelegate.m:
#import "AppDelegate.h"
#import "ViewController.h"
@implementation AppDelegate
@synthesize window = _window;
@synthesize facebook;
@synthesize delegate;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ViewController *viewController = [[ViewController alloc] init];
kAppID = @"385380598149062";
facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:viewController];
return YES;
}
- (void)showSession {
NSLog(@"FB Session: %@", [NSNumber numberWithBool:[facebook isSessionValid]]);
}
@end
如您所见,这些方法中没有发生太多事情。委托类是ViewController。我在 AppDelegate 中真正做的就是初始化 Facebook 实例。就这一点而言,这是整个 ViewController.m(减去一些非 Facebook 相关的内容):
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize contacts, contactArray;
- (void)viewDidLoad
{
[super viewDidLoad];
defaults = [NSUserDefaults standardUserDefaults];
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
facebook = delegate.facebook;
[facebook setSessionDelegate:self];
[self loginToFacebook:nil];
eventsArray = [[NSMutableArray alloc] initWithObjects:@"Event one", @"Event two", nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation = UIInterfaceOrientationPortrait);
} else {
return NO;
}
}
- (void)loginToFacebook:(id)sender {
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
NSLog(@"accessToken:%@\n expiry:%@", facebook.accessToken, facebook.expirationDate);
}
if (![facebook isSessionValid]) {
[facebook authorize:nil];
}
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"handle open url");
return [facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [facebook handleOpenURL:url];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
//ok so it's a dictionary with one element (key="data"), which is an array of dictionaries, each with "name" and "id" keys
fbContacts = [(NSDictionary *)result objectForKey:@"data"];
NSLog(@"Request did load");
for (int i=0; i<[fbContacts count]; i++) {
NSDictionary *friend = [fbContacts objectAtIndex:i];
long long fbid = [[friend objectForKey:@"id"]longLongValue];
NSString *name = [friend objectForKey:@"name"];
NSLog(@"id: %lld - Name: %@", fbid, name);
}
}
- (void)fbDidLogin {
NSLog(@"FB did log in");
[defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
[defaults synchronize];
[facebook requestWithGraphPath:@"me/friends" andDelegate:self];
}
- (void)fbDidNotLogin:(BOOL)cancelled {
NSLog(@"FB login cancelled");
}
/**
* Called after the access token was extended. If your application has any
* references to the previous access token (for example, if your application
* stores the previous access token in persistent storage), your application
* should overwrite the old access token with the new one in this method.
* See extendAccessToken for more details.
*/
- (void)fbDidExtendToken:(NSString*)accessToken
expiresAt:(NSDate*)expiresAt {
NSLog(@"FB extended token");
}
/**
* Called when the user logged out.
*/
- (void)fbDidLogout {
NSLog(@"FB logged out");
[defaults removeObjectForKey:@"FBAccessTokenKey"];
[defaults removeObjectForKey:@"FBExpirationDateKey"];
[defaults synchronize];
}
/**
* Called when the current session has expired. This might happen when:
* - the access token expired
* - the app has been disabled
* - the user revoked the app's permissions
* - the user changed his or her password
*/
- (void)fbSessionInvalidated {
NSLog(@"FB session invalidated");
}
@end
.plist 看起来很棒,也许你只是忘记了 openurl 处理程序?
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
}
更新:
作为一个实验,你可以尝试一下这个(来自 Hackbook 的例子):
// Now check that the URL scheme fb[app_id]://authorize is in the .plist and can
// be opened, doing a simple check without local app id factored in here
NSString *url = [NSString stringWithFormat:@"fb%@://authorize",kAppId];
BOOL bSchemeInPlist = NO; // find out if the sceme is in the plist file.
NSArray* aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
if ([aBundleURLTypes isKindOfClass:[NSArray class]] &&
([aBundleURLTypes count] > 0)) {
NSDictionary* aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0];
if ([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]) {
NSArray* aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"];
if ([aBundleURLSchemes isKindOfClass:[NSArray class]] &&
([aBundleURLSchemes count] > 0)) {
NSString *scheme = [aBundleURLSchemes objectAtIndex:0];
if ([scheme isKindOfClass:[NSString class]] &&
[url hasPrefix:scheme]) {
bSchemeInPlist = YES;
}
}
}
}
// Check if the authorization callback will work
BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]];
if (!bSchemeInPlist || !bCanOpenUrl) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Setup Error"
message:@"Invalid or missing URL scheme. You cannot run the app until you set up a valid URL scheme in your .plist."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil,
nil];
[alertView show];
[alertView release];
}
在这一步我们会知道,URL 方案是正确的。
尝试改变 [脸书授权:无]; 和 [facebook 授权:[[NSArray alloc] initWithObjects:@"read_friendlists", nil]]; 所以也许 SSO 需要至少指定一项权限。
我遇到了同样的问题,我被重定向到 Facebook 应用程序,并且身份验证对话框立即被取消,让我留在 Facebook 应用程序中。
问题出在.plist中,我忘记在URL方案中的appID号之前输入fb。
(来源:facebook.com)
如果您的委托方法仍未触发,那是因为您必须将所有 facebook 逻辑放入应用程序的委托中。我还启用了上面所说的 aurav 又名 sparsh。
经过长时间的努力终于找到了这个问题的解决方案,我不知道它是否正确,但它对我的应用程序来说就像魅力一样:
访问developer.facebook.com
从列表中选择您的应用程序(您在 URL 方案中使用的应用程序)
如果您的应用程序被选为本机应用程序,那么它将要求提供捆绑包标识符
向他提供您构建应用程序时使用的包标识符
如果您使用通配符捆绑标识符,则提供 com.product.abc 等,否则提供完整的捆绑标识符。
您的 FB 登录将开始为您工作。