I'm using a Facebook SDK with FBConnect
. On my MainAppDelegate.m, I used this code:
#import "MainAppDelegate.h"
#import "MenuViewController.h"
#import "LoginViewController.h"
#import "DataSet.h"
static NSString* kAppId = @"1234567891234567";
@implementation MainAppDelegate
@synthesize window = _window;
@synthesize mainViewController = _mainViewController;
@synthesize viewController = _viewController;
//Facebook 2.0
@synthesize navigationController=_navigationController;
@synthesize facebook;
@synthesize apiData;
@synthesize userPermissions;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Facebook SDK 2
// Setup view controllers
LoginViewController *loginViewController = [[LoginViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:loginViewController];
[navController.navigationBar setTintColor:[UIColor colorWithRed:0/255.0
green:51.0/255.0
blue:102.0/255.0
alpha:1.0]];
[navController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
[navController.navigationBar setHidden:YES];
self.navigationController = navController;
[loginViewController release];
[navController release];
// Initialize Facebook
facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:loginViewController];
// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}
// Initialize API data (for views, etc.)
apiData = [[DataSet alloc] init];
// Initialize user permissions
userPermissions = [[NSMutableDictionary alloc] initWithCapacity:1];
// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
if ( facebook.isSessionValid ) {
self.mainViewController = [[MenuViewController alloc] initWithNibName:@"MenuViewController" bundle:nil];
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];
} else {
self.viewController = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
}
//End of Facebook SDK 2
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
//Facebook 2
// Although the SDK attempts to refresh its access tokens when it makes API calls,
// it's a good practice to refresh the access token also when the app becomes active.
// This gives apps that seldom make api calls a higher chance of having a non expired
// access token.
[[self facebook] extendAccessTokenIfNeeded];
}
- (void)dealloc {
[_window release];
[_navigationController release];
[facebook release];
[apiData release];
[userPermissions release];
[super dealloc];
}
#pragma mark -
#pragma mark Facebook SDK 2
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
}
And on my LoginViewController which is the main UIViewController
of my app is thus:
#import "LoginViewController.h"
#import "MenuViewController.h"
#import "MainAppDelegate.h"
#import "FBConnect.h"
#import "APICallsViewController.h"
@implementation LoginViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
if (![[delegate facebook] isSessionValid]) {
[self showLoggedOut];
} else {
[self showLoggedIn];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
# pragma mark - Events
-(IBAction)clickedFacebook:(id)sender {
buttonFacebook.userInteractionEnabled = NO;
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
if (![[delegate facebook] isSessionValid]) {
permissions = [[NSArray alloc] initWithObjects:@"offline_access",@"user_relationships",@"user_hometown",@"user_location",@"user_birthday",@"email",@"user_work_history", nil];
[[delegate facebook] authorize:permissions];
} else {
[self showLoggedIn];
}
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
buttonFacebook.enabled = YES;
NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [NSString stringWithFormat:@"%@/user.archive",dir];
if( [[NSFileManager defaultManager] fileExistsAtPath:path] ) {
MenuViewController *system = [[MenuViewController alloc] initWithNibName:nil bundle:nil];
[self.view addSubview:system.view];
}
pendingApiCallsController = nil;
}
#pragma - Private Helper Methods
/**
* Show the logged in menu
*
* Login
*/
- (void)showLoggedIn {
MenuViewController *system = [[MenuViewController alloc] initWithNibName:nil bundle:nil];
[self.view addSubview:system.view];
[self apiFQLIMe];
}
/**
* Show the logged out in menu
*
* Logout
*/
- (void)showLoggedOut {}
/**
* Show the authorization dialog.
*/
- (void)login {
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
if (![[delegate facebook] isSessionValid]) {
[[delegate facebook] authorize:permissions];
} else {
[self showLoggedIn];
}
}
/**
* Invalidate the access token and clear the cookie.
*/
- (void)logout {
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
[[delegate facebook] logout];
}
#pragma mark - Facebook API Calls
/**
* Make a Graph API Call to get information about the current logged in user.
*/
- (void)apiFQLIMe {
NSString *fql = [[NSString alloc] initWithString:@"SELECT uid, name, pic, sex, relationship_status, hometown_location, current_location, birthday, email, work, locale FROM user WHERE uid=me()"];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:fql, @"query", nil ];
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
[[delegate facebook] requestWithMethodName:@"fql.query"
andParams:params
andHttpMethod:@"POST"
andDelegate:self];
}
/*
* Call this method to make a request to the Graph API.
*
* You should set up your delegate to handle the API results including error scenarios.
*/
- (void)apiGraphUserPermissions {
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
[[delegate facebook] requestWithGraphPath:@"me/permissions" andDelegate:self];
}
- (void)storeAuthData:(NSString *)accessToken expiresAt:(NSDate *)expiresAt {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:accessToken forKey:@"FBAccessTokenKey" ];
[defaults setObject:expiresAt forKey:@"FBExpirationDateKey" ];
[defaults synchronize];
}
#pragma mark - FBSessionDelegate Methods
/**
* Called when the user has logged in successfully.
*/
- (void)fbDidLogin {
[self showLoggedIn];
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
[self storeAuthData:[[delegate facebook] accessToken] expiresAt:[[delegate facebook] expirationDate]];
[pendingApiCallsController userDidGrantPermission];
}
-(void)fbDidExtendToken:(NSString *)accessToken expiresAt:(NSDate *)expiresAt {
[self storeAuthData:accessToken expiresAt:expiresAt];
}
/**
* Called when the user canceled the authorization dialog.
*/
-(void)fbDidNotLogin:(BOOL)cancelled {
[pendingApiCallsController userDidNotGrantPermission];
}
/**
* Called when the request logout has succeeded.
*/
- (void)fbDidLogout {
pendingApiCallsController = nil;
// Remove saved authorization information if it exists and it is
// ok to clear it (logout, session invalid, app unauthorized)
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObjectForKey:@"FBAccessTokenKey"];
[defaults removeObjectForKey:@"FBExpirationDateKey"];
[defaults synchronize];
[self showLoggedOut];
}
#pragma mark - FBRequestDelegate Methods
- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
NSLog(@"did Receive Response");
}
- (void)request:(FBRequest *)request didLoad:(id)result {
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
// This callback can be a result of getting the user's basic
// information or getting the user's permissions.
if ([result objectForKey:@"name"]) {
[self apiGraphUserPermissions];
[self beginGame:result];
} else {
// Processing permissions information
MainAppDelegate *delegate = (MainAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate setUserPermissions:[[result objectForKey:@"data"] objectAtIndex:0]];
}
}
#pragma mark -
#pragma mark Begin Game
-(void)beginGame:(id)user {
// Get user info from Facebook through "user"
//...
// Trying to call MenuViewController
MenuViewController *menu = [[MenuViewController alloc] initWithNibName:nil bundle:nil];
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if( version >= 5.0 ) {
[self presentViewController:menu animated:YES completion:nil];
}else{
[self presentModalViewController:menu animated:YES];
}
[menu release];
}
@end
What should I do to make it work? I feel the problem is in the methods fbDidLogin, didReceiveResponse and the method didLoad.
The sequence methods was:
viewDidLoad
,viewWillAppear
then showLoggedOut
I clicked on facebook button to login and then happen this sequence:
fbDidLogin showLoggedIn viewDidLoad apiFQLIMe storeAuthData
But when the app try to receive a response, it doesn't work and the app crashes with error as follows.
EXC_BAD_ACCESS Code=1 Address:276817x92