2

Я работаю над функцией для приложения iOS, которое позволит его пользователю выбрать фотографию из своей галереи Facebook.Управление фотографиями фотографий пользователей Facebook

У меня есть первоначальный запрос на работу фотографий - он возвращает небольшое количество фотографий и ссылку на следующую и предыдущую партии. Моя проблема в том, что я не знаю, как правильно обращаться с этой страницей; Я долгое время пытался его найти или найти ответ в документации Facebook, но это просто мусор (т. Е. Никакой помощи вообще).

Не могли бы вы взглянуть на метод, который должен иметь дело с этим запросом, и объяснить мне, как добавить остальные фотографии в userablePhotos 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, но решил не тратить больше времени на то, чтобы установить его - я следовал инструкциям в письме, но он все равно бросать ошибки.

ответ

0

Это в основном основано на моих исследованиях, проведенных с использованием метода проб и ошибок, поскольку документация от 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.

Получение альбомов и фотографий пользователя - проблема пагинацией

После того, как пользователь вошел в их сессии обрабатывается за кулисами в API Facebook, так что нет необходимости беспокоиться о том, что мы можем просто выполнить которые мы хотим.

Чтобы получить данные альбомы для пользователя, поместите эту строку в Graph Проводник:

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

Это задаст Fb для подсчета фотографий в каждом альбоме и их идентификаторы. Обратите внимание, что 1-й уровень ответа JSON содержит идентификатор пользователя, а также массив «альбомов», который содержит массив данных. Это массив фактических альбомов, которые нас интересуют.

Имея Идентификаторы каждого альбома мы можем исследовать их фотографии. Ниже вызов будет получать ссылки на источник фото каждого альбома и его миниатюры:

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

где фактический идентификатор альбома, чьи фотографии вы хотите получить.

Первоначальная проблема заключается в том, что, поскольку в альбоме может быть много фотографий, попытка получить их за один раз - это, вероятно, плохая идея - вот почему разработчики Facebook ввели эти разбиения на страницы. Это означает, что вы можете установить лимит количества данных фотографий, которые вы получаете за один вызов, и затем используете «курсор» для следующих/предыдущих партий, которые вы хотите получить, с указанными курсорами, предоставленными вам в каждый звонок. Основная проблема связана с такими разбитыми на страницы данными. Если мы посмотрим на данные, возвращенные в нашем предыдущем вызове, мы увидим, что существует раздел «подкачки» с «курсорами» (который содержит «до» и «после») и «следующий». Ключ «next» - это ссылка, которая очень похожа на нашу строку вызовов, используемую в Graph Explorer, и заканчивается курсором «после»; мы могли бы подумать, то, что можно просто добавить «после» курсор нашего вызова строки

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

и корма, что в Graph Explorer. Неа! По какой-то причине это не сработает, как ожидалось - оно по-прежнему направляет нас к первой партии, а не к следующей. Тем не менее, «следующая» ссылка все еще работает, поэтому можно использовать ее части вместо вызова, который мы сделали в Graph Explorer. Таким образом, вызов, чтобы получить фотографии:

<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 кэшировать следующий URL-адрес из ответа JSON и назначить 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

Смежные вопросы