处理Facebook用户照片的分页 [英] Handle pagination of Facebook user photos

查看:75
本文介绍了处理Facebook用户照片的分页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为iOS应用程序开发一项功能,该功能将使其用户能够从其Facebook画廊中选择一张照片.

I'm working on a feature for an iOS app that will enable its user to pick a photo from their Facebook gallery.

我已经收到了使照片正常工作的初始请求-它确实返回了少量照片以及指向下一批和上一批产品的链接.我的问题是我不知道处理这种分页的正确方法是什么;我花了很长时间尝试搜索它或在Facebook的文档中找到答案,但这只是垃圾(即毫无帮助).

I've got the initial request to get the photos working - it does return a small number of photos and a link to the next and previous batches. My problem is I don't know what the right way of handling this pagination is; I spent a long time trying to google it or find an answer in Facebook's documentation but it's simply rubbish (i.e. no help whatsoever).

您能否看一下应该处理此请求的方法,并向我解释如何将其余照片添加到usersFacebookPhotos可变数组中?

Could you take a look at the method that is supposed to deal with this request and explain to me how to add the rest of the photos to the usersFacebookPhotos mutable array?

NSMutableArray *usersFacebookPhotos;

- (void) getUserPhotoAlbumsWithSuccess:(void (^) (bool))successHandler failure:(void (^) (NSError *error))failureHandler {

    usersFacebookPhotos = (NSMutableArray *)[[NSArray alloc] init];

    FBRequest *fbRequest = [FBRequest requestWithGraphPath:@"me?fields=photos.fields(picture,source)" parameters:nil HTTPMethod:@"GET"];
    [fbRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

        if (!error) {

            NSLog(@"got the initial batch");
            // process the next batch of photos here
        }
        else {

            NSLog(@"error: %@", error);
        }
    }];
}

是的,是的-我尝试使用grabKit,但决定不再花费更多的时间来设置它-我按照字母上的说明进行操作,但仍然会出错.

Oh, and yes - I tried using grabKit but decided not to spend any more time trying to set it up - I followed the instructions to the letter but it would still throw errors.

推荐答案

这主要是基于我使用试错法进行的研究,因为Facebook的文档根本没有帮助.我很高兴学习一种更好的方法:)

This is mostly based on my research carried out using the trial-and-error method as Facebook's documentation wasn't helpful at all. I'm happy to learn of a better method of doing this :)

然后我们可以在模板代码中使用来自Graph Explorer的调用:

We can then use the calls from the Graph Explorer in the template code:

NSString *yourCall = @"YourGraphExplorerCall";

FBRequest *fbRequest = [FBRequest requestWithGraphPath:yourCall parameters:nil HTTPMethod:@"GET"];
[fbRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

if (!error) {

    NSDictionary *jsonResponse = (NSDictionary *) result;
    // Do your stuff with the JSON response
}
else {

    failureHandler(error);
}
}];

Facebook Graph接受和回复JSON.

Facebook Graph accepts and replies in JSON.

获取用户的相册和照片-分页问题

Obtaining a user’s albums and photos - the problem of pagination

用户登录会话后,Facebook API会在后台处理该消息,因此无需担心,我们只需执行所需的特定请求即可.

Once a user is logged in their session is handled behind the scenes by the Facebook API so there’s no need to be concerned about that, we can just perform specific requests we want.

要获取用户的相册数据,请将此字符串放入图形资源管理器"中:

To get the albums data for a user, put this string into the Graph Explorer:

me?fields=albums.fields(count,id)

这将要求Fb提供每个相册中的照片数量及其ID.请注意,JSON回复的第一级包含用户ID以及包含数据"数组的相册"数组-这是我们感兴趣的实际相册的数组.

This’ll ask Fb for the count of photos in each album and their IDs. Notice that the 1st level of the JSON reply contains the ID of the user as well as the "albums" array which contains the "data" array - that’s the array of the actual albums we’re interested in.

有了每个相册的ID,我们可以浏览他们的照片.以下通话将获得每个相册的原始照片及其缩影的链接:

Having the IDs of each album we can explore their photos. The below call will get links to each album’s source photo and its miniature:

<album_id>?fields=photos.fields(source,picture)

您要获取其照片的相册的实际ID在哪里.

where is the actual ID of the album whose photos you want to get.

最初的问题是,由于相册中可能有很多照片,因此一口气尝试这些照片可能不是一个好主意-这就是Facebook开发人员在这些通话中引入分页的原因.这意味着您可以为单次调用中获取的照片数据数量设置一个限制,然后使用光标"表示要获取的下一个/上一个批次,并在其中将光标指示给您.每个电话. 主要问题是处理此类分页数据.如果我们查看上一次调用中返回的数据,可以看到其中有一个分页"部分,其中包含游标"(包含之前"和之后")和下一个". 下一个"键是一个链接,其外观与我们在图形资源管理器"中使用的调用字符串非常相似-并以之后"光标结尾;那么,我们可能会想到,可以将"after"光标简单地附加到我们的调用字符串

The initial problem is that since there might be many photos in an album, trying to get them in one go is probably a bad idea - that’s why Facebook devs introduced pagination into these calls. What this means is that you can set a limit for the number of photos data you get in a single call and you then use a "cursor" for the next/previous batches that you want to get, with said cursors being given to you in each call. The main problem is dealing with such paginated data. If we look at the data returned in our previous call we can see that there’s a "paging" section with "cursors" (which contains "before" and "after") and "next". The "next" key is a link which looks very similar to our call string used in the Graph Explorer - and it ends with the "after" cursor; we could think, then, that it’s possible to simply append the "after" cursor to our call string

<album_id>?fields=photos.fields(source,picture)&after=<after_cursor>

,然后将其输入到图形资源管理器"中.没有!由于某些原因,该操作无法按预期进行-它仍将我们定向到第一批而不是下一批. 但是,下一个"链接仍然有效,因此可以使用其中的一部分而不是我们对图形资源管理器"的调用.因此,调用获取照片:

and feed that into the Graph Explorer. Nope! For some reason this won’t work as expected - it still directs us to the first batch instead of the next one. However, the "next" link still works so it’s possible to use parts of it instead of the call we made to the Graph Explorer. Thus the call to get the photos:

<album_id>?fields=photos.fields(source,picture)

成为:

<album_id>/photos?fields=source%2Cpicture&limit=25

此外,在添加& after =后,它仍然可以使用:

Moreover, it still works after being appended with &after=:

<album_id>/photos?fields=source%2Cpicture&limit=25&after=

因此,很容易在每次调用中简单地获取"next"的值并将其附加到上面的字符串中,以便下次调用.

Thus it’s easy to simply get the value of "next" in each call for a batch and append it to the above string for the next call.

这是代码最终版本的摘录:

Here’s the snippet of the final version of the code:

NSString *const FACEBOOK_GRAPH_LIST_ALBUMS = @"me?fields=albums.fields(count,id,name)";
NSString *const FACEBOOK_GRAPH_LIST_ALBUM_PHOTOS = @"/photos?fields=source%2Cpicture&limit=25&after=";
NSArray *currentUsersFacebookAlbums;

- (void) getUserPhotosWithSuccess:(void (^) ())successHandler failure:(void (^) (NSError *error))failureHandler {

    FBRequest *fbRequest = [FBRequest requestWithGraphPath:FACEBOOK_GRAPH_LIST_ALBUMS parameters:nil HTTPMethod:@"GET"];
    [fbRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

        if (!error) {

            NSDictionary *jsonResponse = (NSDictionary *) result;
            currentUsersFacebookAlbums = (NSArray *) [[jsonResponse valueForKey:@"albums"] valueForKey:@"data"];

            for (NSDictionary *currentAlbum in currentUsersFacebookAlbums) {

                NSString *albumId = [currentAlbum valueForKey:@"id"];
                [self getCurrentUserFacebookPhotosWithAlbum:albumId afterCursor:nil failure:^(NSError *error) {
                    failureHandler(error);
                }];
            }

            successHandler();
        }
        else {

            failureHandler(error);
        }
    }];
}

- (void) getCurrentUserFacebookPhotosWithAlbum:(NSString *) albumId afterCursor:(NSString *) afterCursor failure:(void (^) (NSError *error))failureHandler {

    if (afterCursor == nil) {

        afterCursor = @"";
    }

    NSString *fbGraphCall = [NSString stringWithFormat:@"%@%@%@", albumId, FACEBOOK_GRAPH_LIST_ALBUM_PHOTOS, afterCursor];

    FBRequest *fbRequest = [FBRequest requestWithGraphPath:fbGraphCall parameters:nil HTTPMethod:@"GET"];
    [fbRequest startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {

        if (!error) {

            NSDictionary *jsonResponse = (NSDictionary *) result;
            NSArray *currentPhotoBatch = (NSArray *) [jsonResponse valueForKey:@"data"];

            // Go through the currently obtained batch and add them to the returned mutable array
            for (NSDictionary *currentPhoto in currentPhotoBatch) {

                [[CurrentUserDataHandler sharedInstance] addFacebookPhoto:currentPhoto];
            }

            // If there's a "next" link in the response, recur the method on the next batch...
            if ([[jsonResponse valueForKey:@"paging"] objectForKey:@"next"] != nil) {

                // ...by appending the "after" cursor to the call
                NSString *afterCursor = [[[jsonResponse valueForKey:@"paging"] valueForKey:@"cursors"] valueForKey:@"after"];
                [self getCurrentUserFacebookPhotosWithAlbum:albumId afterCursor:afterCursor failure:^(NSError *error) {
                    failureHandler(error);
                }];
            }

            if ([[jsonResponse valueForKey:@"paging"] objectForKey:@"next"] != nil && [self isLastAlbum:albumId]) {

                [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_FACEBOOK_PHOTOS object:nil];
            }
        }
        else {

            failureHandler(error);
        }
    }];
}

- (bool) isLastAlbum:(NSString *) albumId {

    for (NSDictionary *albumData in currentUsersFacebookAlbums) {

        if ([albumId isEqualToString:[albumData valueForKey:@"id"]] && [currentUsersFacebookAlbums indexOfObject:albumData] == [currentUsersFacebookAlbums count] - 1) {

            return YES;
        }
    }

    return NO;
}

这篇关于处理Facebook用户照片的分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆