3

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
4

0 回答 0