2

我正在研究iOS应用的一项功能,该功能将使其用户能够从他们的Facebook图库中选择一张照片。处理Facebook用户照片的分页

我已经有了最初的请求来让照片工作 - 它确实会返回少量的照片以及指向下一批和上一批的链接。我的问题是我不知道处理这个分页的正确方法是什么;我花了很长时间尝试谷歌它或在Facebook的文档中找到答案,但它只是垃圾(即没有任何帮助)。

你可以看看应该处理这个请求的方法,并向我解释如何将其余照片添加到用户的FacebookPhotos可变数组?

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但决定不花更多的时间试图将其设置 - 我也跟着信中的说明,但它仍然会引发错误。

回答

0

这主要是基于我使用试错法进行的研究,因为Facebook的文档根本没有帮助。我很高兴地知道这样做的更好的方法:)

然后,我们可以使用从图形管理器的模板代码的调用:

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的图形接受和JSON回复。

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

的问题,一旦用户登录他们的会议通过Facebook的API在幕后进行处理,所以没有必要关心的是,我们可以只执行我们想要的具体请求。

要获得专辑数据用户,把这个字符串转换成图形浏览器:

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

这会问FB中的每张专辑及其ID照片的数量。请注意,JSON回复的第一级包含用户的ID以及包含“数据”阵列的“albums”数组 - 这是我们感兴趣的实际相册的阵列。

拥有我们可以探索他们的照片,每个相册的ID。下面的通话将获得链接到每一张专辑的图片来源及微型:

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

哪里是你想获得其照片的相册的实际ID。

最初的问题是,由于专辑中可能有很多照片,试图让它们一次性完成可能是一个糟糕的主意 - 这就是为什么Facebook将这些调用引入分页的原因。这意味着您可以设置一次调用中获得的照片数据的数量限制,然后使用“光标”指定想要获取的下一批/上一批批次,并将所述光标放入每次通话。 主要问题是处理这样的分页数据。如果我们查看之前调用中返回的数据,我们可以看到“分页”部分包含“游标”(包含“之前”和“之后”)和“下一个”。 “下一个”键是一个链接,它看起来与我们在图形浏览器中使用的调用字符串非常相似 - 它以“之后”光标结束;我们能想到的,那么,它可能仅仅是“后”光标追加到我们的电话串

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

和饲料是进入图形浏览器。不!出于某种原因,这不会按预期工作 - 它仍然指引我们到第一批,而不是下一批。 但是,“下一个”链接仍然有效,因此可以使用它的一部分而不是我们对图形浏览器的调用。因此,调用来获取照片:

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

变为:

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

此外,它仍然有效=后&被追加后:

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

因此它很容易简单地得到在批次的每个调用中的“next”的值并将其附加到上一个字符串以用于下一个调用。

这里的代码的最终版本的片段:

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; 
} 
+0

见http://stackoverflow.com/questions/29909534/ios-fetch-facebook-friends-with-pagination-using-next/43365360#43365360 –

0

对于Facebook的分页我会建议使用苹果机类的

使用nextPageURL变量缓存从JSON响应下一个URL并指定在下次API请求的URL字符串,如果nextPageURL不是零和使用下面的代码:

if (self.nextPageURL) { 
    // urlString is the first time formulated url string 
    urlString = self.nextPageURL; 
} 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]]; 
[NSURLConnection sendAsynchronousRequest:request queue:networkQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
    if (error) { 
     DDLogVerbose(@"FACEBOOK:Connection error occured: %@",error.description); 
    }else{ 
     isRequestProcessing = NO; 
     NSDictionary *resultData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; 
     DDLogVerbose(@"parsed data is %@",resultData); 
     self.nextPageURL = resultData[@"paging"][@"next"]; 

     // do your customisation of resultData here. 
     } 
    } 
}]; 
3

我用递归函数调用为了解决这个问题,我设置了一个10的下限来测试功能。

-(void)facebookCall { 
    [self getFBFriends:@"me/friends?fields=name,picture.type(large)&limit=10"]; 
} 

-(void)getFBFriends:(NSString*)url { 
    [FBRequestConnection startWithGraphPath:url 
         completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { 
          if (!error) { 
           [self parseFBResult:result]; 

           NSDictionary *paging = [result objectForKey:@"paging"]; 
           NSString *next = [paging objectForKey:@"next"]; 

           // skip the beginning of the url https://graph.facebook.com/ 
           // there's probably a more elegant way of doing this 

           NSLog(@"next:%@", [next substringFromIndex:27]); 

           [self getFBFriends:[next substringFromIndex:27]]; 

          } else { 
           NSLog(@"An error occurred getting friends: %@", [error localizedDescription]); 
          } 
         }]; 
} 

-(void)parseFBResult:(id)result { 

    NSLog(@"My friends: %@", result); 

    NSArray *data = [result objectForKey:@"data"]; 
    int j = 0; 
    for(NSDictionary *friend in data){ 
     NSDictionary *picture = [friend objectForKey:@"picture"]; 
     NSDictionary *picData = [picture objectForKey:@"data"]; 
     NSLog(@"User:%@, picture URL: %@", [friend objectForKey:@"name"], [picData objectForKey:@"url"]); 
     j++; 
    } 
    NSLog(@"No of friends is: %d", j); 

} 
+0

看到更播放由规则在这里回答:http://stackoverflow.com/a/12223324/850608 – Elsint