iOS Facebook Graph API 使用“下一个”或“上一个”Url 使用 SDK 进行分页

Posted

技术标签:

【中文标题】iOS Facebook Graph API 使用“下一个”或“上一个”Url 使用 SDK 进行分页【英文标题】:iOS Facebook Graph API Use "next" or "previous" Url for Pagination Using SDK 【发布时间】:2014-07-01 15:37:29 【问题描述】:

我不太确定在对结果进行分页时想要利用图形 api 返回的“下一个”或“上一个”URL 时的最佳方法或正确的 SDK 调用。我已经查看了 FBRequest 和 FBRequestConnection 的文档,但没有任何方法或调用可以作为我问题的明显解决方案。任何人有一个或可以提出一个建议,将我指向正确的方向?

【问题讨论】:

【参考方案1】:

Nikolay 的解决方案非常完美。这是它的 Swift 版本

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)")
    

【讨论】:

【参考方案2】:

要获得下一个链接,您必须这样做:

我是这样解决的:

添加标题

#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];

使用方法:

获取好友列表使用如下技术:

//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);
                  ];
];

【讨论】:

【参考方案3】:

所以在寻找明显答案的过程中,我偶然发现了 github.com 上的 Facebook ios SDK 源代码并找到了这个类:https://github.com/facebook/facebook-ios-sdk/blob/master/src/Network/FBGraphObjectPagingLoader.m。

在“- (void)followNextLink”方法中,我找到了解决方案:

 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];

上面有/有很多我不需要的代码,所以我能够(在SO OP 的帮助下)将其浓缩为:

/* 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];

为了帮助可能需要更通用方法的其他人,我已将我的大部分 Facebook API 图调用编译成一个 gist,发现 @https://gist.github.com/tamitutor/c65c262d8343d433cf7f。

【讨论】:

非常感谢!

以上是关于iOS Facebook Graph API 使用“下一个”或“上一个”Url 使用 SDK 进行分页的主要内容,如果未能解决你的问题,请参考以下文章

Facebook iOS SDK(Graph API) 无法访问公共页面信息

iOS 我可以从 Graph api Facebook 获取上传进度吗?

如何确定用户是不是已使用 Graph API 从 Facebook iOS 注销?

使用 Facebook IOS SDK 3.1 和 Graph API 发布带有标题的图片

与 Facebook Graph API /user-id/feed (iOS) 一起使用的 viewController

Facebook Graph API Explorer 和 iOS SDK API 调用返回不同的结果