2012-04-05 121 views
4

我在将facebook集成到我的iOS应用中时遇到了问题。当我启动我的应用时,它会重定向到Facebook应用,这很好。但是auth对话框只是从屏幕上消失了(就像一个被驳回的模式视图控制器),委托方法不会触发,我留在facebook应用程序中而不是被重定向回到我的应用程序。我显然没有成功初始化会话。我遵循iOS教程中的步骤,但我一定在某处出错了。我见过的大多数问题都是关于错误或试图从auth对话中获得不同的行为。如果这是一个骗局,请直接指向我相同的问题,因为我在这里打墙。我已经按照教程中的说明设置了我的.plist。我使用从iTunes连接抓取的应用程序的包标识符。我的常量kAppID是我从Facebook Developer应用程序界面获得的AppID。仔细阅读了FB静态库的头文件和实现文件,以及FB的文档和教程,在我看来,如果我想要做的就是重定向到FB应用程序,请登录并重定向到我自己的应用程序,这些步骤加上下面的代码应该足够了。ios5中的Facebook SSO

在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。 enter image description here

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中做的是init实例。关于这一点,herre是整个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 
+0

你能说明你在.plist文件中完成了什么吗?我认为问题应该在那里... – dmirkitanov 2012-04-05 22:06:33

+0

编辑,谢谢你看看。 – geraldWilliam 2012-04-05 22:14:41

+0

嗨。你可以发布你的appdelegate文件吗?** – 2012-04-05 22:23:25

回答

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

UPD:

  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]; 与 [facebook授权:[[NSArray alloc] initWithObjects:@“read_friendlists”,nil]]; 所以也许SSO需要至少指定一个权限。

+0

没有那东西在那里。我怀疑(基于当我强制授权通过Safari时发现的内容),我将无效URL传递给FB授权对话框,这可能是我们未获得授权或返回到我的应用程序的原因。该应用程序在iTunes商店中不可用(因为它处于开发的早期阶段)。最初在Facebook上注册该应用程序时导致了某种警告,但随后警告消失了,我认为我们很乐意去。我不可能需要在商店上提供我的应用程序才能做到这一点?!?! – geraldWilliam 2012-04-05 22:33:55

+0

对不起,在我在ViewController.m代码中看到它之前发布了它。不,afaik无论您的appstore ID是否在应用程序设置中指定,都没有区别。 – dmirkitanov 2012-04-05 22:44:09

+0

在facebook设置页面中,是否已选中“为iOS SSO配置”?而在高级设置中,应用类型应该是“Native/Desktop”..现在没有更多的想法。 – dmirkitanov 2012-04-05 22:52:59

0

挣扎了很长一段时间后,终于得到了一个解决这个问题,我不其正确的,但它的工作般的魅力对我的应用程序:

去developer.facebook.com

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

如果你的应用程序被选为本地应用程序,那么它会要求提供包标识符

如果您使用通配符包标识符提供类似com.product.abc的提供方式,那么可以使用它提供捆绑包标识符,否则将提供完整的包标识符。

您的FB登录将开始为您工作。 your settings must be like as shown in image

2

我有同样的问题,我被重定向到facebook应用程序,auth对话框立即被解散,离开了我的Facebook应用程序。

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

plist

如果你的委托方法仍然无法射击,那是因为你必须把所有的Facebook的逻辑在应用程序的委托。我还启用了aurav aka sparsh上面所说的东西。

+0

非常感谢你发布了这个。 – jmosesman 2012-08-20 05:01:44