まったく同じ問題に対処しました。これが私の解決策です:
基本的に次のメソッドを含む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 のものは、このシングルトン クラスで管理されます。
私の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 スペースに保存していることがわかります。Web サービスへの認証として accessToken を使用しているためです。
私の 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