facebookios6accountsocial-framework

Facebook integration iOS 6 Social/Accounts Frameworks


I want to code a singleton for facebook integration with iOS 6. I use Social and Accounts Frameworks.

This my FacebookData.h :

@class FacebookData;

@protocol FacebookDataDelegate <NSObject>
@optional
- (void)FacebookDataDidLoadRequest:(NSDictionary *)result;
- (void)FacebookDataDidFailToLoadRequest:(NSError *)error;
@end

@interface FacebookData : NSObject{
    NSString *facebookAppID;
    ACAccountStore *facebookAccountStore;
    ACAccountType *facebookAccountType;
    ACAccount *facebookAccount;
    BOOL readPermissionsGranted;
    BOOL RequestPermissionsGranted;
}

@property (nonatomic) id delegate;

+ (FacebookData*)sharedFacebookData;

- (void)setAppID:(NSString *)appID;
- (NSString *)currentAppID;
- (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest;
- (void)loadRequest:(NSString*)theRequest;

@end

The most important methods of my FacebookData.m :

    - (void)requestPermissions:(NSArray*)Permissions andLoadRequest:(NSString*)theRequest{

    if(!readPermissionsGranted){

    __block NSArray *facebookPermissions = @[@"read_stream", @"email"];

    __block NSDictionary *facebookOptions = @{   ACFacebookAppIdKey : facebookAppID,
                                         ACFacebookAudienceKey : ACFacebookAudienceFriends,
                                         ACFacebookPermissionsKey : facebookPermissions};

    [facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted, NSError *error)
     {
         if (granted) {

             readPermissionsGranted = YES;
             [self requestPermissions:Permissions andLoadRequest:theRequest];

         }

         // If permission are not granted to read.
         if (!granted)
         {
             NSLog(@"Read permission error: %@", [error localizedDescription]);
             [self.delegate FacebookDataDidFailToLoadRequest:error];
             readPermissionsGranted = NO;

             if ([[error localizedDescription] isEqualToString:@"The operation couldn’t be completed. (com.apple.accounts error 6.)"])
             {
                 [self performSelectorOnMainThread:@selector(showError) withObject:error waitUntilDone:NO];
             }
         }

     }];

    }else{

        __block NSArray *facebookPermissions = [NSArray arrayWithArray:Permissions];        
        __block NSDictionary *facebookOptions = @{   ACFacebookAppIdKey : facebookAppID,
                                                     ACFacebookAudienceKey : ACFacebookAudienceFriends,
                                                     ACFacebookPermissionsKey : facebookPermissions};

        [facebookAccountStore requestAccessToAccountsWithType:facebookAccountType options:facebookOptions completion:^(BOOL granted2, NSError *error)
         {
             if (granted2)
             {
                 RequestPermissionsGranted = YES;
                 // Create the facebook account
                 facebookAccount = [[ACAccount alloc] initWithAccountType:facebookAccountType];
                 NSArray *arrayOfAccounts = [facebookAccountStore accountsWithAccountType:facebookAccountType];
                 facebookAccount = [arrayOfAccounts lastObject];
                 [self loadRequest:theRequest];
                 NSLog(@"Permission granted");
             }

             if (!granted2)
             {
                 NSLog(@"Request permission error: %@", [error localizedDescription]);
                 [self.delegate FacebookDataDidFailToLoadRequest:error];
                 RequestPermissionsGranted = NO;
             }

         }];

    }
}

- (void)loadRequest:(NSString*)theRequest{

    __block NSDictionary *result= [[NSDictionary alloc]init];
    // Create the URL to the end point
    NSURL *theURL = [NSURL URLWithString:theRequest];

    // Create the SLReqeust
    SLRequest *slRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:theURL parameters:nil];

    // Set the account
    [slRequest setAccount:facebookAccount];

    // Perform the request
    [slRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
        if (error)
        {
            // If there is an error we populate the error string with error
            __block NSString *errorString = [NSString stringWithFormat:@"%@", [error localizedDescription]];
            NSLog(@"Error: %@", errorString);
            [self.delegate FacebookDataDidFailToLoadRequest:error];

        } else
        {
            NSLog(@"HTTP Response: %i", [urlResponse statusCode]);
            NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
            result = jsonResponse;
            [self.delegate FacebookDataDidLoadRequest:jsonResponse];
        }

    }];
}

I use this singleton like this :

FacebookData *data = [FacebookData sharedFacebookData];
data.delegate = self;
[data setAppID:APPIDKEY];
[data requestPermissions:@[@"friends_location"]     andLoadRequest:@"https://graph.facebook.com/me/friends?fields=id,name,location"];

This request with this permissions fails whereas the same method with permissions :@[@"email"] and request: https://graph.facebook.com/me/friends works perfectly.

This is the error that I can see in the console :

error =     {
        code = 2500;
        message = "An active access token must be used to query information about the current user.";
        type = OAuthException;
    };

I can't find where the bug is, I don't know how to use tokens with these frameworks.

Thanks for your help !


Solution

  • IMO your LoadRequest URL is not correct

    andLoadRequest:@"https://graph.facebook.com/me/friends?fields=id,name,location"];

    SLRequest gives an oauth error even though its real problem with the URL. SLRequest doesn't support "?fields=id,name,location" directly in URL. You need to pass them as parameter in SLRequest

    See the example below:

    NSString* queryString = NULL;
    queryString = [NSString stringWithFormat:@"https://graph.facebook.com/me/friends", nil];
    NSURL *friendsRequestURL = [NSURL URLWithString:queryString];
        SLRequest *friendsRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
                                                             requestMethod:SLRequestMethodGET URL:friendsRequestURL
                                                              parameters:@{@"fields":@"id,name,location"}];
    

    PS: I was facing the similar problem last night and cursing the facebook for given wrong error statement. But finally able to solve it at the end. :)