2011-08-29 28 views
2

我正在制作一个应用程序,我需要在多个视图控制器中调用请求。我不希望Facebook登录屏幕在应用程序启动时显示。只有在用户未登录时用户点击另一个视图控制器中的按钮时才应该打开它,因此将代码放在应用程序委托中并不能解决问题。而且,在Facebook API中请求数据的整个异步过程正在令我失望,我开始松散了头发。如何在iOS上正确使用Facebook Graph API

一个具有静态方法的类,用于获取facebook对象并将其视为单例。

#import "PBSocialMedia.h" 
#import "PBFacebookDelegate.h" 

static Facebook *facebook; 
static PBFacebookDelegate *facebookDelegate; 

@implementation PBSocialMedia 

+ (Facebook *)sharedFacebook { 

    if (facebook == nil) { 
     facebookDelegate = [[PBFacebookDelegate alloc] init]; 
     facebook = [[Facebook alloc] initWithAppId:@"156687441079334" andDelegate:facebookDelegate]; 
    } 

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    if ([defaults objectForKey:@"FBAccessTokenKey"] 
     && [defaults objectForKey:@"FBExpirationDateKey"]) { 
     facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"]; 
     facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"]; 
    } 

    NSArray *permissions = [NSArray arrayWithObjects:@"user_photo_video_tags", @"friends_photo_video_tags", @"user_photos", @"friends_photos", nil]; 

    if (![facebook isSessionValid]) { 
     [facebook authorize:permissions]; 
    } else { 
     [[NSNotificationCenter defaultCenter] postNotificationName:@"connectedToFacebook" object:self]; 
    } 

    return facebook; 
} 

+ (Facebook *)sharedFacebookWithoutAuthorizing { 
    return facebook; 
} 

@end 

实现上述

#import "PBFacebookDelegate.h" 
#import "PBSocialMedia.h" 

@implementation PBFacebookDelegate 

/** 
* Called when the user successfully logged in. 
*/ 
- (void)fbDidLogin { 
    Facebook *facebook = [PBSocialMedia sharedFacebook]; 

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"]; 
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"]; 
    [defaults synchronize]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"connectedToFacebook" object:self]; 
} 

/** 
* Called when the user dismissed the dialog without logging in. 
*/ 
- (void)fbDidNotLogin:(BOOL)cancelled { 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissedFacebookDialog" object:self]; 
} 

/** 
* Called when the user logged out. 
*/ 
- (void)fbDidLogout { 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"disconnectedFromFacebook" object:self]; 
} 


@end 

在课堂上使用Facebook的会议代表当你从两个班见上面,我利用的通知,让我知道什么时候A类用户登录/离开Facebook。下面的代码是的,我怎么想使用它的一个例子:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    Facebook *facebook = [PBSocialMedia sharedFacebook]; 

    if (self.canUseGraphAPI) { 
     [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self]; 
     NSLog(@"Can use"); 
    } else { 
     NSLog(@"Can't use"); 
    } 
} 

- (void)connectedToFacebook { 
    self.canUseGraphAPI = YES; 
} 

- (void)disconnectedFromFacebook { 
    self.canUseGraphAPI = NO; 
} 

如预期,因为愚蠢的异步请求的这ofcourse不工作。只有当用户登录时它才能正确工作。所以当我第一次打开应用程序时,它调用[PBSocialMedia sharedFacebook];然后它继续执行请求函数并且不等待sharedFacebook函数完成。我真的希望有人遇到过这个问题。我想在我的代码中的不同位置执行请求,但仅当用户登录时才需要进行请求,并且在用户登录前需要等待,然后再请求。下面的代码不起作用,但它显示了我想要的!

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    Facebook *facebook = [PBSocialMedia sharedFacebook]; 

    while (self.canUseGraphAPI) { 
     // WAITING FOR LOGIN IN 
    } 

    [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self]; 
} 

- (void)connectedToFacebook { 
    self.canUseGraphAPI = YES; 
} 

- (void)disconnectedFromFacebook { 
    self.canUseGraphAPI = NO; 
} 

回答

2

我将开始重组你的代码通过传递你想在得到您的回答从FB回到执行块工作。这与您在jQuery中如何使用ajax相似。

- (void)viewDidLoad { 
[super viewDidLoad]; 

Facebook *facebook = [PBSocialMedia sharedFacebook]; 

[self withGraphAPIDo: ^{ 
    [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self]; 
    }]; 
} 
+0

谢谢回答!你能解释更多吗?你的意思是多少重组?我应该放弃通知吗?当我调用“sharedFacebook”函数时,它几乎会立即继续到块的下一行。我很抱歉,但我不明白如何做到这一点。 – LuckyLuke

+0

我正在使用MGTwitterEngine来完成这个工作,它会为每个请求返回一个唯一的字符串,您可以使用它来跟踪响应。所以我调整它将响应块存储到由请求ID键入的字典中。当请求回调进入时,我通过请求ID查找字典中的块,然后执行它。 – 2011-08-30 18:02:44

相关问题