Facebook Connect Class with Singleton:Access token issue [英] Facebook Connect Class with Singleton : Access token issue
问题描述
我已经创建了一个名为LoginFacebook的单一类,用于将用户连接到Facebook并执行不同的请求。问题是我收到一个关于access_token的错误。这里是:
3:< CFString 0x4c552f0 [0xe50400]> {content =message} =< CFString 0x4c55250 [0xe50400]> {content =必须使用活动的访问令牌来查询有关当前用户的信息。
首先,我通过从另一个视图控制器发出以下请求来连接到Facebook:
[[LoginFacebook loginFacebook] launchFacebook:self]
然后我从同一个其他View Controller发出另一个方法的第二个请求:
[[LoginFacebook loginFacebook] requireName:self]
这是我的单身班LoginFacebook:
LoginFacebook.h:
#import< UIKit / UIKit.h>
#importLoginFacebook.h
@interface FirstViewController:UIViewController {
}
- (IBAction)performConnect :((id )发送者;
- (IBAction)performName:(id)sender;
@end
LoginFacebook.m:
#importLoginFacebook.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]
&&&&default; ]。
facebook.expirationDate = [defaults objectForKey:@FBExpirationDateKey];
}
if(![facebook isSessionValid]){
[facebook authorize:nil delegate:self];
}
}
- (NSString *)requireName:(id)sender
{
NSLog(@requireName asked);
[facebook requestWithGraphPath:@meandDelegate:self];
返回名称;
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; //表示不能被释放的对象
}
- (void)release {
// do nothing
}
- (id)autorelease {
return self;
}
// FBRequestDelegate
/ **
*当Facebook API请求返回响应时调用。这个回调
*可以让您访问原始响应。在
*(void)请求之前调用:(FBRequest *)请求didLoad:(id)result,
*传递解析的响应对象。
* /
- (void)request:(FBRequest *)请求didReceiveResponse:(NSURLResponse *)响应{
NSLog(@received response);
}
/ **
*当请求返回并且其响应已解析为
*对象时调用。结果对象可以是字典,数组,字符串,
*或数字,具体取决于API响应的格式。如果您需要访问原始响应
*,请使用:
*
*(void)request:(FBRequest *)请求
* didReceiveResponse :( NSURLResponse *)响应
* /
- (void)request:(FBRequest *)request didLoad:(id)result {
if([result isKindOfClass:[NSArray class]]){
result = [ result objectAtIndex:0];
}
name = [result objectForKey:@name];
NSLog(@request didLoad);
};
/ **
*当错误阻止Facebook API请求成功完成
*时调用。
* /
- (void)request:(FBRequest *)请求didFailWithError:(NSError *)错误{
name = [error localizedDescription];
NSLog(@----请求didFailWithError);
NSLog(@%@,[error localizedDescription]);
NSLog(@%@,[错误描述]);
};
//////////////////////////////////// ////////////////////////
// FBDialogDelegate
/ **
* UIServer对话框成功返回时调用。
* /
- (void)dialogDidComplete:(FBDialog *)对话框{
name = @发布成功;
}
@end
另请注意,我添加以下方法(与.h中相应的FacebookLogin * facebook)到我的应用程序代理:
- (BOOL)应用程序: (UIApplication *)application handleOpenURL :( NSURL *)url {
return [facebook handleOpenURL:url];
}
你们中间有人知道那里有什么问题吗?我一直在努力处理这两天的代码...
从错误信息看来,你的访问令牌是' t已经有效了,或者你甚至没有访问令牌。您的应用程序在用户第一次尝试访问Facebook时是否实际打开Web浏览器?如果没有,那么你可能无法正确配置项目。
也许这是一个好主意,分享我的Facebook单身人士的代码 - 我相信代码是很干净,容易理解&扩大。由于我的需求目前非常谦虚,我只有一种方法来授权(登录)和另一种方法来发布到墙上。我正在使用堆栈,所以我可以按照正确的顺序执行一些操作(例如,如果用户还没有登录,就可以在发布消息到墙前登录)。
SDFacebookController.h
import< Foundation / Foundation.h>
#importFBConnect.h
@interface SDFacebookController:NSObject
< FBSessionDelegate,
FBRequestDelegate>
@property(非原子,保留)Facebook * facebook;
+(SDFacebookController *)sharedController;
- (void)authorize;
- (void)postMessageToWall:(NSString *)消息;
@end
SDFacebookController.m
$$ b
$ b $$
@interface SDFacebookController()
@property(nonatomic,retain)SDOperationStack * operationStack;
- (void)performAuthorization;
- (void)performPostMessageToWall:(NSString *)消息;
- (void)runOperation;
@end
@implementation SDFacebookController
@synthesize Facebook,operationStack;
#pragma mark - 实例方法
- (void)authorize
{
NSInvocationOperation * operation = [[[NSInvocationOperation alloc] initWithTarget:self selector :@selector(performAuthorization)object:nil] autorelease];
[operationStack push:operation];
[self runOperation];
}
- (void)postMessageToWall:(NSString *)消息
{
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 - 私有方法
- (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,@消息,nil];
[facebook requestWithGraphPath:@me / feedandParams:params andHttpMethod:@POSTandDelegate:self];
}
#pragma mark - FBRequestDelegate
/ **
*在请求发送到服务器之前调用。
* /
- (void)requestLoading:(FBRequest *)request
{
DLog(@%@,request);
}
/ **
*当服务器响应并开始发回数据时调用。
* /
- (void)请求:( FBRequest *)请求didReceiveResponse :( NSURLResponse *)响应
{
DLog(@%@%@,请求,响应);
}
/ **
*当错误阻止请求成功完成时调用。
* /
- (void)请求:( FBRequest *)请求didFailWithError :( NSError *)错误
{
DLog(@%@%@,请求,错误);
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@Error,nil)
message:[error localizedDescription]
委托:nil
cancelButtonTitle:NSLocalizedString (@OK,nil)
otherButtonTitles:nil]
autorelease] show];
[operationStack empty];
}
/ **
*当请求返回并且其响应已解析为
*对象时调用。
*
*结果对象可能是字典,数组,字符串或数字,
*取决于API响应的格式。
* /
- (void)请求:( FBRequest *)请求didLoad:(id)result
{
DLog(@%@%@,请求,结果) ;
if([operationStack isEmpty] == NO)
[self runOperation];
else if([operationStack.lastOperation.invocation selector] == @selector(performPostMessageToWall :))
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@MessagePosted,nil)
消息:NSLocalizedString(@在Facebook上成功发布消息,nil)
委托:nil
cancelButtonTitle:NSLocalizedString(@OK,nil)
otherButtonTitles:nil]
autorelease] show];
}
/ **
*当请求返回响应时调用。
*
*结果对象是NSData类型的服务器的原始响应
* /
- (void)request:(FBRequest *)请求didLoadRawResponse :( NSData *)数据
{
DLog(@%@%@,请求,数据);
}
#pragma mark - FBSessionDelegate
/ **
*用户登录成功后调用
* /
- (void)fbDidLogin
{
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:@FBAccessTokenKey];
[defaults setObject:[facebook expirationDate] forKey:@FBExpirationDateKey];
[默认同步];
}
/ **
*当用户在没有登录的情况下关闭对话框时调用
* /
- (void)fbDidNotLogin:(BOOL )取消
{
}
/ **
*用户注销时调用。
* /
- (void)fbDidLogout
{
}
#pragma标记 - 内存管理
- (id)init
{
self = [super init];
if(self)
{
facebook = [[Facebook alloc] initWithAppId:kFacebookAppIdentifier];
operationStack = [[SDOperationStack alloc] init];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
if([defaults objectForKey:@FBAccessTokenKey]&&&默认对象ForKey:@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];
});
返回控制器;
}
@end
SDOperationStack.h
#import< Foundation / Foundation.h>
@interface SDOperationStack:NSObject
@property(nonatomic,retain)NSInvocationOperation * lastOperation;
- (void)push:(NSOperation *)操作;
- (NSOperation *)pop;
- (BOOL)isEmpty;
- (void)empty;
@end
SDOperationStack.m / p>
#importSDOperationStack.h
@interface SDOperationStack()
@property(nonatomic,retain)NSMutableArray *数组;
@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 *)操作
{
[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
I have created a singleton class called "LoginFacebook" which is meant to connect user to Facebook and to perform the different request. The problem is that I get an error about the access_token. Here it is :
3 : <CFString 0x4c552f0 [0xe50400]>{contents = "message"} = <CFString 0x4c55250 [0xe50400]>{contents = "An active access token must be used to query information about the current user."}
First I connect to Facebook by making the following request from another View Controller :
[[LoginFacebook loginFacebook] launchFacebook:self]
Then I make that second request from the same other View Controller but from another method :
[[LoginFacebook loginFacebook] requireName:self]
Here is my singleton class "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
Please also note that I added the following method (with the corresponding FacebookLogin *facebook in the .h) to my App Delegate :
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [facebook handleOpenURL:url];
}
Does one of you know what is going wrong there ? I have been struggling with the code for 2 days now...
From the error message it seems your access token isn't valid anymore or you didn't even have an access token yet. Does your app actually open a web browser the first time a user is trying to access Facebook? If not, then you probably failed to configure the project properly.
Perhaps it'd be a good idea to share the code of my Facebook singleton - I believe the code is pretty clean and easy to understand & expand. Since my needs are currently very modest I only have a method to authorize (login) and another method to post to wall. I'm using a stack so I can perform some operations in the correct order (for example login before posting message to wall, if user isn't logged in yet).
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
这篇关于Facebook Connect Class with Singleton:Access token issue的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!