4

我在将 facebook 集成到我的 iOS 应用程序时遇到问题。当我启动我的应用程序时,它会重定向到 facebook 应用程序,这很好。但是身份验证对话框只是从屏幕上消失了(就像一个关闭的模式视图控制器),委托方法没有触发,我留在了 facebook 应用程序中,而不是被重定向回我的应用程序。我显然没有成功初始化会话。我按照 iOS 教程中的步骤进行操作,但我一定是在某个地方出错了。我看到的大多数问题都是关于错误或试图从身份验证对话框中获得不同的行为。如果这是一个骗局,请引导我回答相同的问题,因为我在这里碰壁了。我已经按照教程中的说明设置了我的 .plist。我使用了从 iTunes 连接中获取的应用程序包标识符。我的常量 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
4

3 回答 3

2

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

升级版:

  1. 作为一个实验,你可以试试这个(来自 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 方案是可以的。

  2. 尝试更改 [facebook authorize:nil]; with [facebook 授权:[[NSArray alloc] initWithObjects:@"read_friendlists", nil]]; 所以也许 SSO 至少需要指定一个权限。

于 2012-04-05T22:28:05.530 回答
2

我遇到了同样的问题,我被重定向到 facebook 应用程序,并且身份验证对话框被立即关闭,让我留在了 facebook 应用程序中。

问题出在 .plist 中,我忘记在 URL Schemes 中的 appID 号之前输入 fb。

列表

如果您的委托方法仍未触发,那是因为您必须将所有 facebook 逻辑放入应用程序的委托中。我还启用了上面所说的 aurav aka sparsh。

于 2012-07-21T15:40:49.633 回答
0

经过长时间的努力终于找到了解决这个问题的方法,我不正确,但它对我的应用程序来说就像魅力一样:

去 developer.facebook.com

从列表中选择您的应用程序(应用程序是您在 URL 方案中使用的应用程序)

如果您的应用程序被选为本机应用程序,那么它将要求提供捆绑标识符

通过您正在构建您的应用程序向他提供捆绑标识符

如果您使用通配符捆绑标识符,则提供类似 com.product.abc 否则提供完整捆绑标识符。

并且您的 FB 登录将开始为您工作。您的设置必须如图所示

于 2012-07-10T11:31:13.117 回答