IOS Facebook Graph API Use the "next" or "previous" URL to paginate using the SDK

I'm not quite sure about the best approach or the right SDK call to do when you want to use the "next" or "previous" URLs returned by the api chart when the results are paginated. I looked through the documentation for FBRequest and FBRequestConnection, but there were no methods or calls that popped up on me as an obvious solution to my problem. Does anyone have or can I make an offer that will point me in the right direction?

+4
source share
3 answers

So, in search of an explicit answer, I stumbled upon the source of the iOS SDK for iOS on github.com and found this class: https://github.com/facebook/facebook-ios-sdk/blob/master/src/Network/FBGraphObjectPagingLoader. m .

Within the " - (void)followNextLink" method, I found my solution:

 FBRequest *request = [[FBRequest alloc] initWithSession:self.session
                                                  graphPath:nil];

    FBRequestConnection *connection = [[FBRequestConnection alloc] init];
    [connection addRequest:request completionHandler:
     ^(FBRequestConnection *innerConnection, id result, NSError *error) {
         _isResultFromCache = _isResultFromCache || innerConnection.isResultFromCache;
         [innerConnection retain];
         self.connection = nil;
         [self requestCompleted:innerConnection result:result error:error];
         [innerConnection release];
     }];

    // Override the URL using the one passed back in 'next'.
    NSURL *url = [NSURL URLWithString:self.nextLink];
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    connection.urlRequest = urlRequest;

    self.nextLink = nil;

    self.connection = connection;
    [self.connection startWithCacheIdentity:self.cacheIdentity
                      skipRoundtripIfCached:self.skipRoundtripIfCached];

The above / had a lot of code that I don't need, so I was able (with this SO OP ) to condense it to:

/* make the API call */
FBRequest *request = [[FBRequest alloc] initWithSession:FBSession.activeSession graphPath:nil];
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
[connection addRequest:request completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithDictionary:@{@"friends": [result objectForKey:@"data"], @"paging": [result objectForKey:@"paging"]}];
    NSLog(@"%@", dictionary);
    block(dictionary, error);
}];

// Override the URL using the one passed back in 'next|previous'.
NSURL *url = [NSURL URLWithString:paginationUrl];
NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
connection.urlRequest = urlRequest;

[connection start];

To help others who might need a more general approach, I have collected most of my graphical Facebook API calls in gist, found @ https://gist.github.com/tamitutor/c65c262d8343d433cf7f .

+3
source

To get the following link, you must do the following:

I solved it like this:

#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>

//use this general method with any parameters you want. All requests will be handled correctly

- (void)makeFBRequestToPath:(NSString *)aPath withParameters:(NSDictionary *)parameters success:(void (^)(NSArray *))success failure:(void (^)(NSError *))failure
{
    //create array to store results of multiple requests
    NSMutableArray *recievedDataStorage = [NSMutableArray new];

    //run requests with array to store results in
    [self p_requestFriendsFromPath:aPath
                        parameters:parameters
                           storage:recievedDataStorage
                            succes:success
                           failure:failure];
}




 - (void)p_requestFromPath:(NSString *)path parameters:(NSDictionary *)params storage:(NSMutableArray *)friends succes:(void (^)(NSArray *))success failure:(void (^)(NSError *))failure
{
    //create requests with needed parameters
        FBSDKGraphRequest *fbRequest = [[FBSDKGraphRequest alloc]initWithGraphPath:path
                                                                         parameters:params
                                                                         HTTPMethod:nil];

    //then make a Facebook connection
    FBSDKGraphRequestConnection *connection = [FBSDKGraphRequestConnection new];
    [connection addRequest:fbRequest
         completionHandler:^(FBSDKGraphRequestConnection *connection, NSDictionary*result, NSError *error) {

             //if error pass it in a failure block and exit out of method
             if (error){
                 if(failure){
                    failure(error);
                 }
                 return ;
             }
             //add recieved data to array
             [friends addObjectsFromArray:result[@"data"];
             //then get parameters of link for the next page of data
             NSDictionary *paramsOfNextPage = [FBSDKUtility dictionaryWithQueryString:result[@"paging"][@"next"]];
             if (paramsOfNextPage.allKeys.count > 0){
                 [self p_requestFromPath:path
                              parameters:paramsOfNextPage
                                 storage:friends
                                  succes:success
                                 failure:failure];
                 //just exit out of the method body if next link was found
                 return;
             }
             if (success){
                success([friends copy]);
             }
         }];
     //do not forget to run connection
    [connection start];
}

:

, , followig:

//For example retrieve friends list with limit of retrieving data items per request equal to 5

NSDictionary *anyParametersYouWant = @{@"limit":@5};
[self makeFBRequestToPath:@"me/taggable_friends/"
           withParameters:anyParametersYouWant
                  success:^(NSArray *results) {
                      NSLog(@"Found friends are:\n%@",results);    
                  }
                  failure:^[(NSError *) {
                      NSLog(@"Oops! Something went wrong(\n%@",error);
                  }];
];
+8

Nikolai’s decision is wonderful. Here is his Swift Version

func makeFBRequestToPath(aPath:String, withParameters:Dictionary<String, AnyObject>, success successBlock: (Array<AnyObject>?) -> (), failure failureBlock: (NSError?) -> ())
{
    //create array to store results of multiple requests
    let recievedDataStorage:Array<AnyObject> = Array<AnyObject>()

    //run requests with array to store results in
    p_requestFromPath(aPath, parameters: withParameters, storage: recievedDataStorage, success: successBlock, failure: failureBlock)
}


func p_requestFromPath(path:String, parameters params:Dictionary<String, AnyObject>, var storage friends:Array<AnyObject>, success successBlock: (Array<AnyObject>?) -> (), failure failureBlock: (NSError?) -> ())
{
    //create requests with needed parameters


    let req = FBSDKGraphRequest(graphPath: path, parameters: params, tokenString: FBSDKAccessToken.currentAccessToken().tokenString, version: nil, HTTPMethod: "GET")
    req.startWithCompletionHandler({ (connection, result, error : NSError!) -> Void in
        if(error == nil)
        {
            print("result \(result)")

            let result:Dictionary<String, AnyObject> = result as! Dictionary<String, AnyObject>


            //add recieved data to array
            friends.append(result["data"]!)
            //then get parameters of link for the next page of data

            let nextCursor:String? = result["paging"]!["next"]! as? String

            if let _ = nextCursor
            {
                let paramsOfNextPage:Dictionary = FBSDKUtility.dictionaryWithQueryString(nextCursor!)

                if paramsOfNextPage.keys.count > 0
                {
                    self.p_requestFromPath(path, parameters: paramsOfNextPage as! Dictionary<String, AnyObject>, storage: friends, success:successBlock, failure: failureBlock)
                    //just exit out of the method body if next link was found
                    return
                }
            }

            successBlock(friends)
        }
        else
        {
            //if error pass it in a failure block and exit out of method
            print("error \(error)")
            failureBlock(error)
        }
    })
}


func getFBFriendsList()
{
    //For example retrieve friends list with limit of retrieving data items per request equal to 5
    let anyParametersYouWant:Dictionary = ["limit":2]
    makeFBRequestToPath("/me/friends/", withParameters: anyParametersYouWant, success: { (results:Array<AnyObject>?) -> () in
        print("Found friends are: \(results)")
        }) { (error:NSError?) -> () in
            print("Oops! Something went wrong \(error)")
    }
}
+8
source

Source: https://habr.com/ru/post/1546712/


All Articles