这主要基于我使用试错法进行的研究,因为 Facebook 的文档根本没有帮助。我很高兴知道这样做的更好方法:)
然后我们可以在模板代码中使用来自 Graph Explorer 的调用:
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 API 在幕后处理,因此无需担心,我们只需执行我们想要的特定请求。
要获取用户的专辑数据,请将此字符串放入 Graph Explorer:
me?fields=albums.fields(count,id)
这将要求 Facebook 提供每个相册中的照片数量及其 ID。请注意,JSON 回复的第一级包含用户的 ID 以及包含“data”数组的“albums”数组 - 这是我们感兴趣的实际专辑的数组。
有了每个相册的 ID,我们就可以浏览他们的照片。以下调用将获取每个相册的源照片及其缩影的链接:
<album_id>?fields=photos.fields(source,picture)
您要获取其照片的相册的实际 ID 在哪里。
最初的问题是,由于相册中可能有很多照片,因此尝试一次性获取它们可能是一个坏主意 - 这就是 Facebook 开发人员在这些调用中引入分页的原因。这意味着您可以为在单个呼叫中获得的照片数据数量设置限制,然后您可以使用“光标”来获取您想要获得的下一个/上一个批次,并将所述光标提供给您每次通话。
主要问题是处理这种分页数据。如果我们查看之前调用中返回的数据,我们可以看到有一个“分页”部分,其中包含“光标”(包含“之前”和“之后”)和“下一个”。
“next”键是一个链接,看起来与我们在 Graph Explorer 中使用的调用字符串非常相似——它以“after”光标结尾;那么,我们可以认为,可以简单地将“after”光标附加到我们的调用字符串
<album_id>?fields=photos.fields(source,picture)&after=<after_cursor>
并将其输入到图形资源管理器中。没有!由于某种原因,这不会按预期工作 - 它仍然将我们引导到第一批而不是下一批。
但是,“下一个”链接仍然有效,因此可以使用它的一部分来代替我们对 Graph Explorer 的调用。因此调用获取照片:
<album_id>?fields=photos.fields(source,picture)
变成:
<album_id>/photos?fields=source%2Cpicture&limit=25
而且,加上 &after=: 后它仍然有效:
<album_id>/photos?fields=source%2Cpicture&limit=25&after=
因此,很容易在批处理的每次调用中简单地获取“next”的值,并将其附加到上述字符串以进行下一次调用。
这是最终版本代码的sn-p:
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;
}