Из сообщения об ошибке кажется, что ваш токен доступа больше не действителен или у вас еще не было токена доступа.Открывает ли ваше приложение веб-браузер в первый раз, когда пользователь пытается получить доступ к Facebook?Если нет, то вам, вероятно, не удалось правильно настроить проект.
Возможно, было бы неплохо поделиться кодом моего синглтона 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