1

我正在寻找使用 Facebook Api 在 iOS 应用程序中签入用户。

我想知道我是否在 AppDelegate 中设置了权限,但希望用户从不同的视图控制器签入,我是否必须在每个视图控制器中声明 Facebook 实例以及 FBRequestDelegate、FBSessionDelegate、FBDialogDelegate 委托方法?还是 AppDelegate 中的一次性事情?

谢谢你的帮助。

4

1 回答 1

2

我刚刚处理了完全相同的问题。这是我的解决方案:

我创建了一个FBRequestWrapper,它基本上包含以下方法:

#import <Foundation/Foundation.h>
#import "Facebook.h"

#define FB_APP_ID @"xx"
#define FB_APP_SECRET @"xx"

@interface FBRequestWrapper : NSObject <FBRequestDelegate, FBSessionDelegate>
{
    Facebook *facebook;
    BOOL isLoggedIn;
}

@property (nonatomic, retain) Facebook *facebook;
@property (nonatomic, assign) BOOL isLoggedIn;

+ (id) defaultManager;
- (void) setIsLoggedIn:(BOOL) _loggedIn;
- (void) FBSessionBegin:(id) _delegate;
- (void) FBLogout;
- (void) getFBRequestWithGraphPath:(NSString*) _path andDelegate:(id) _delegate;
- (void) sendFBRequestWithGraphPath:(NSString*) _path params:(NSMutableDictionary*) _params andDelegate:(id) _delegate;

@end

所以所有 Facebook 的东西都在这个 Singleton 类中管理。

在我的AppDelegate 中,我调用了 authentication。因为在我看来,必须在加载所有控制器之前完成身份验证。

// FACEBOOK
requestWrapper = [FBRequestWrapper defaultManager];

BOOL loggedIn = [requestWrapper isLoggedIn];

// if the user is not currently logged in begin the session
if (!loggedIn) {
    [requestWrapper FBSessionBegin:(id)self];
} else {
    NSLog(@"Is already logged in!");
}

// Check if the access token is already there. In that case the user is already authenticated with facebook.
// Directly load the controllers and do not wait till facebook has returned back the access_token
if([[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"] != nil &&
   [[NSUserDefaults standardUserDefaults] objectForKey:@"exp_date"] != nil) {
    [self loadControllers];
}

可以看到我也将 accessToken 存储在 NSUserDefaults 空间中。因为我们使用 accessToken 作为我们的 web 服务的身份验证。

我的 AppDelegate 方法委托 FBSessionDelegate 方法:

@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate, FBSessionDelegate>

这是最重要的方法fbDidLogin的实现:

- (void) fbDidLogin {
    NSLog(@"AccessToken: %@", requestWrapper.facebook.accessToken);

    [[NSUserDefaults standardUserDefaults] setObject:requestWrapper.facebook.accessToken forKey:@"access_token"];
    [[NSUserDefaults standardUserDefaults] setObject:requestWrapper.facebook.expirationDate forKey:@"exp_date"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [self loadControllers];
}

在这里,我将 accesstoken 存储在 NSUserDefaults 中,如果一切正常,则加载所有控制器。

现在,如果您想从 AppDelegate 之外的任何控制器访问 Facebook Graph Api,您也可以像这样使用 FBRequestWrapper:

- (IBAction)test:(id)sender {
   // FBRequestWrapper
   NSString *graphPath = @"me/friends";

   [[FBRequestWrapper defaultManager] getFBRequestWithGraphPath:graphPath andDelegate:self];
}

这里是来自 FBRequestWrapper.m 的代码:

#import "FBRequestWrapper.h"

static FBRequestWrapper *defaultWrapper = nil;

@implementation FBRequestWrapper
@synthesize isLoggedIn, facebook;

+ (id) defaultManager {

    if (!defaultWrapper)
        defaultWrapper = [[FBRequestWrapper alloc] init];

    return defaultWrapper;
}

- (void) setIsLoggedIn:(BOOL) _loggedIn {
    isLoggedIn = _loggedIn;

    if (isLoggedIn) {
        [[NSUserDefaults standardUserDefaults] setObject:facebook.accessToken forKey:@"access_token"];
        [[NSUserDefaults standardUserDefaults] setObject:facebook.expirationDate forKey:@"exp_date"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    else {
        [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"access_token"];
        [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"exp_date"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}

- (void) FBSessionBegin:(id) _delegate {

    if (facebook == nil) {
        facebook = [[Facebook alloc] initWithAppId:FB_APP_ID andDelegate:_delegate];
        [facebook setSessionDelegate:_delegate];

        NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];
        NSDate *exp = [[NSUserDefaults standardUserDefaults] objectForKey:@"exp_date"];

        if (token != nil && exp != nil && [token length] > 2) {
            isLoggedIn = YES;
            facebook.accessToken = token;
            facebook.expirationDate = [NSDate distantFuture];

            [self setIsLoggedIn:isLoggedIn];

            NSLog(@"Access token: %@", facebook.accessToken);
        } 
    }

    if(![facebook isSessionValid]) {
        NSArray *permissions = [NSArray arrayWithObjects:@"offline_access", @"read_friendlists", @"user_about_me", nil];

        // if no session is available login
        [facebook authorize:permissions];
    }
}
- (void) FBLogout {
    [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"access_token"];
    [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"exp_date"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [facebook logout:self];
}

// Make simple requests
- (void) getFBRequestWithGraphPath:(NSString*) _path andDelegate:(id) _delegate {
    if (_path != nil) {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

        if (_delegate == nil)
            _delegate = self;

        if(isLoggedIn) {
            NSLog(@"is logged in in the get method");
        } else {
            NSLog(@"Is NOT logged in the get metthod");
        }

        [facebook requestWithGraphPath:_path andDelegate:_delegate];
    }
}

// Used for publishing
- (void) sendFBRequestWithGraphPath:(NSString*) _path params:(NSMutableDictionary*) _params andDelegate:(id) _delegate {

    if (_delegate == nil)
        _delegate = self;

    if (_params != nil && _path != nil) {

        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
        [facebook requestWithGraphPath:_path andParams:_params andHttpMethod:@"POST" andDelegate:_delegate];
    }
}

#pragma mark -
#pragma mark FacebookSessionDelegate

- (void)fbDidLogin {
    isLoggedIn = YES;

    [[NSUserDefaults standardUserDefaults] setObject:facebook.accessToken forKey:@"access_token"];
    [[NSUserDefaults standardUserDefaults] setObject:facebook.expirationDate forKey:@"exp_date"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)fbDidNotLogin:(BOOL)cancelled {
    isLoggedIn = NO;
}

- (void)fbDidLogout {
    [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"access_token"];
    [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"exp_date"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    isLoggedIn = NO;
}


#pragma mark -
#pragma mark FBRequestDelegate

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    //NSLog(@"ResponseFailed: %@", error);
}

- (void)request:(FBRequest *)request didLoad:(id)result {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    //NSLog(@"Parsed Response: %@", result);
}


/**
 * 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 did extend token.. NOT IMPLEMENTED YET!");
}

/**
 * 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.. NOT IMPLEMENTED YET!");
}

@end
于 2012-04-12T14:58:40.910 回答