2011-08-16 74 views
3

我創建了一個名爲「登錄Facebook」的單身人士班,旨在將用戶連接到Facebook並執行不同的請求。問題是我得到關於access_token的錯誤。那就是:Facebook Connect類與單身人士:訪問令牌問題

3 : <CFString 0x4c552f0 [0xe50400]>{contents = "message"} = <CFString 0x4c55250 [0xe50400]>{contents = "An active access token must be used to query information about the current user."} 

首先,我連接到Facebook,通過從其他視圖控制器做出如下要求:

[[LoginFacebook loginFacebook] launchFacebook:self] 

然後我就可以對同其他視圖控制器,但是從另一種方法第二個請求:

[[LoginFacebook loginFacebook] requireName:self] 

這裏是我的單例類 「LoginFacebook」:

LoginFacebook.h : 

#import <UIKit/UIKit.h> 
#import "LoginFacebook.h" 

@interface FirstViewController : UIViewController { 

} 

-(IBAction)performConnect:(id)sender; 
-(IBAction)performName:(id)sender; 

@end 

LoginFacebook.m:

#import "LoginFacebook.h" 
static LoginFacebook *loginFacebook = nil; 

@implementation LoginFacebook 
@synthesize name; 
@synthesize facebook; 

-(void)launchFacebook:(id)sender 
{ 

permissions = [[NSArray arrayWithObjects: 
@"read_stream", @"publish_stream", @"offline_access",nil] retain]; 

Facebook* facebookbis = [[Facebook alloc] initWithAppId:@"168938499825684"]; 
facebook = facebookbis; 
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
if ([defaults objectForKey:@"FBAccessTokenKey"] 
&& [defaults objectForKey:@"FBExpirationDateKey"]) { 
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"]; 
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"]; 
} 
if (![facebook isSessionValid]) { 
[facebook authorize:nil delegate:self]; 
} 
} 

-(NSString *)requireName:(id)sender 
{ 
NSLog(@"requireName asked"); 
[facebook requestWithGraphPath:@"me" andDelegate:self]; 
return name; 
NSLog(@"%@",[facebook accessToken]); 
} 


+ (LoginFacebook *)loginFacebook 
{ 
if (loginFacebook == nil) { 
loginFacebook = [[super allocWithZone:NULL] init]; 
} 
return loginFacebook; 
} 

+ (id)allocWithZone:(NSZone *)zone { 
return [[self loginFacebook] retain]; 
} 

- (id)copyWithZone:(NSZone *)zone { 
return self; 
} 

- (id)retain { 
return self; 
} 

- (NSUInteger)retainCount { 
return NSUIntegerMax; //denotes an object that cannot be released 
} 

- (void)release { 
//do nothing 
} 

- (id)autorelease { 
return self; 
} 

// FBRequestDelegate 

/** 
* Called when the Facebook API request has returned a response. This callback 
* gives you access to the raw response. It's called before 
* (void)request:(FBRequest *)request didLoad:(id)result, 
* which is passed the parsed response object. 
*/ 
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response { 
NSLog(@"received response"); 
} 

/** 
* Called when a request returns and its response has been parsed into 
* an object. The resulting object may be a dictionary, an array, a string, 
* or a number, depending on the format of the API response. If you need access 
* to the raw response, use: 
* 
* (void)request:(FBRequest *)request 
*  didReceiveResponse:(NSURLResponse *)response 
*/ 
- (void)request:(FBRequest *)request didLoad:(id)result { 
if ([result isKindOfClass:[NSArray class]]) { 
result = [result objectAtIndex:0]; 
} 
name = [result objectForKey:@"name"]; 
NSLog(@"request didLoad"); 
}; 

/** 
* Called when an error prevents the Facebook API request from completing 
* successfully. 
*/ 
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error { 
name = [error localizedDescription]; 
NSLog(@"----request didFailWithError"); 
NSLog(@"%@", [error localizedDescription]); 
NSLog(@"%@", [error description]); 
}; 


//////////////////////////////////////////////////////////////////////////////// 
// FBDialogDelegate 

/** 
* Called when a UIServer Dialog successfully return. 
*/ 
- (void)dialogDidComplete:(FBDialog *)dialog { 
name = @"publish successfully"; 
} 

@end 

另外請注意,我添加了以下方法(與在.H相應FacebookLogin * Facebook的),以我的應用程序代表:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { 

return [facebook handleOpenURL:url]; 
} 

是否之一你知道那裏發生了什麼問題嗎?我一直在努力的代碼2天...

回答

2

從錯誤消息看來你的訪問令牌不再有效,或者你甚至還沒有訪問令牌。用戶第一次嘗試訪問Facebook時,您的應用程序是否實際打開了Web瀏覽器?如果沒有,那麼你可能沒有正確配置項目。

也許它會是分享我的Facebook單的代碼是一個好主意 - 我相信代碼是很乾淨,很容易理解&擴大。由於我的需求目前非常適中,我只有一種方法來授權(登錄)和另一種方法來發布到牆上。我正在使用堆棧,因此我可以按正確順序執行一些操作(例如,在將消息發佈到牆上之前登錄,如果用戶尚未登錄)。

SDFacebookController.h

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

@interface SDFacebookController : NSObject 
    <FBSessionDelegate, 
    FBRequestDelegate> 

@property (nonatomic, retain) Facebook *facebook; 

+ (SDFacebookController *)sharedController; 
- (void)authorize; 
- (void)postMessageToWall:(NSString *)message; 
@end 

SDFacebookController.m

#import "SDFacebookController.h" 
#import "Constants+Macros.h" 
#import "SDOperationStack.h" 


@interface SDFacebookController() 
@property (nonatomic, retain) SDOperationStack *operationStack; 
- (void)performAuthorization; 
- (void)performPostMessageToWall:(NSString *)message; 
- (void)runOperation; 
@end 


@implementation SDFacebookController 
@synthesize facebook, operationStack; 

#pragma mark - Instance methods 

- (void)authorize 
{ 
    NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performAuthorization) object:nil] autorelease]; 
    [operationStack push:operation]; 

    [self runOperation]; 
} 

- (void)postMessageToWall:(NSString *)message 
{ 
    NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performPostMessageToWall:) object:message] autorelease]; 
    [operationStack push:operation]; 

    if (![facebook isSessionValid]) 
    { 
     NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performAuthorization) object:nil] autorelease]; 
     [operationStack push:operation]; 
    } 

    [self runOperation]; 
} 

#pragma mark - Private methods 

- (void)runOperation 
{ 
    NSOperation *operation = [operationStack pop]; 
    [[NSOperationQueue currentQueue] addOperation:operation]; 
} 

- (void)performAuthorization 
{ 
    if (![facebook isSessionValid]) 
    { 
     NSArray *permissions = [NSArray arrayWithObject:@"publish_stream"]; 
     [facebook authorize:permissions delegate:self]; 
    } 
} 

- (void)performPostMessageToWall:(NSString *)message 
{ 
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:message, @"message", nil]; 
    [facebook requestWithGraphPath:@"me/feed" andParams:params andHttpMethod:@"POST" andDelegate:self]; 
} 

#pragma mark - FBRequestDelegate 

/** 
* Called just before the request is sent to the server. 
*/ 
- (void)requestLoading:(FBRequest *)request 
{ 
    DLog(@"%@", request); 
} 

/** 
* Called when the server responds and begins to send back data. 
*/ 
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response 
{ 
    DLog(@"%@ %@", request, response); 
} 

/** 
* Called when an error prevents the request from completing successfully. 
*/ 
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error 
{ 
    DLog(@"%@ %@", request, error); 

    [[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) 
           message:[error localizedDescription] 
           delegate:nil 
         cancelButtonTitle:NSLocalizedString(@"OK", nil) 
         otherButtonTitles:nil] 
    autorelease] show]; 

    [operationStack empty]; 
} 

/** 
* Called when a request returns and its response has been parsed into 
* an object. 
* 
* The resulting object may be a dictionary, an array, a string, or a number, 
* depending on thee format of the API response. 
*/ 
- (void)request:(FBRequest *)request didLoad:(id)result 
{ 
    DLog(@"%@ %@", request, result); 

    if ([operationStack isEmpty] == NO) 
     [self runOperation]; 
    else if ([operationStack.lastOperation.invocation selector] == @selector(performPostMessageToWall:)) 
     [[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"MessagePosted", nil) 
            message:NSLocalizedString(@"Successfully posted message on Facebook.", nil) 
            delegate:nil 
         cancelButtonTitle:NSLocalizedString(@"OK", nil) 
         otherButtonTitles:nil] 
     autorelease] show]; 
} 

/** 
* Called when a request returns a response. 
* 
* The result object is the raw response from the server of type NSData 
*/ 
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data 
{ 
    DLog(@"%@ %@", request, data); 
} 

#pragma mark - FBSessionDelegate 

/** 
* Called when the user successfully logged in. 
*/ 
- (void)fbDidLogin 
{ 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"]; 
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"]; 
    [defaults synchronize]; 
} 

/** 
* Called when the user dismissed the dialog without logging in. 
*/ 
- (void)fbDidNotLogin:(BOOL)cancelled 
{ 

} 

/** 
* Called when the user logged out. 
*/ 
- (void)fbDidLogout 
{ 

} 

#pragma mark - Memory management 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    {  
     facebook = [[Facebook alloc] initWithAppId:kFacebookAppIdentifier]; 
     operationStack = [[SDOperationStack alloc] init]; 

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

- (void)dealloc 
{ 
    [operationStack release]; 
    [facebook release]; 
    [super dealloc]; 
} 

#pragma mark - Singleton 

+ (SDFacebookController *)sharedController 
{ 
    static SDFacebookController *controller = nil; 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     controller = [[self alloc] init]; 
    }); 

    return controller; 
} 

@end 

SDOperationStack.h

#import <Foundation/Foundation.h> 

@interface SDOperationStack : NSObject 

@property (nonatomic, retain) NSInvocationOperation *lastOperation; 

- (void)push:(NSOperation *)operation; 
- (NSOperation *)pop; 
- (BOOL)isEmpty; 
- (void)empty; 

@end 

SDOperationStack.m

#import "SDOperationStack.h" 


@interface SDOperationStack() 
@property (nonatomic, retain) NSMutableArray *array; 
@end 


@implementation SDOperationStack 
@synthesize array, lastOperation; 

- (void)dealloc 
{ 
    [lastOperation release]; 
    [array release]; 
    [super dealloc]; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     array = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void)push:(NSInvocationOperation *)operation 
{ 
    [array addObject:operation]; 
} 

- (NSInvocationOperation *)pop 
{ 
    if ([self isEmpty]) 
     return nil; 

    self.lastOperation = (NSInvocationOperation *)[array lastObject]; 
    [array removeLastObject]; 
    return lastOperation; 
} 

- (BOOL)isEmpty 
{ 
    return [array count] == 0; 
} 

- (void)empty 
{ 
    [array removeAllObjects]; 
} 

@end 
+1

我終於設法得到它。 問題是,FBRequestDelegate將在ViewController類中實現,該類將發送請求到單例。 您可以使用巴里真正全面的教程http://barrycenter.com/BAM!coding/2011/07/simplifying-facebook-ios-sdk/ 感謝您的時間Wolfgang Schreurs! – EricDumont