iOS: fetch Facebook friends with pagination using 'next' - ios

I am trying to fetch 'taggable_friends' list from Facebook, where there may be more than 1000 taggable friends, so Facebook paginates the results. Here is the method.
-(void)getsFbTaggableFriends:(NSString *)nextCursor dicFBFriends:(NSMutableArray *) dicFriends failure:(void (^) (NSError *error))failureHandler
{
NSString *qry = #"/me/taggable_friends";
NSMutableDictionary *parameters;
if (nextCursor == nil) {
parameters = nil;
}
else {
parameters = [[NSMutableDictionary alloc] init];
[parameters setValue:nextCursor forKey:#"next"];
}
[FBRequestConnection startWithGraphPath:qry
parameters:parameters
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
if (error) {
NSLog(#"%#", [error localizedDescription]);
}else {
/* handle the result */
NSMutableDictionary *mDicResult = [[NSMutableDictionary alloc]initWithDictionary:result];
for (NSDictionary * fbItem in [mDicResult valueForKey:#"data"])
{
[dicFriends addObject:fbItem];
}
// if 'next' value is found, then call recursively
if ([[mDicResult valueForKey:#"paging"] objectForKey:#"next"] != nil) {
NSString *nextCursor = mDicResult[#"paging"][#"next"];
NSLog(#"next:%#", [nextCursor substringFromIndex:27]);
[self getsFbTaggableFriends:nextCursor dicFBFriends:dicFriends failure:^(NSError *error) {
failureHandler(error);
}];
}
}
}];
}
Problem:
I get first 1000 records in the 'result' object and the value of the 'next' key is passed as the "parameters" parameter for the recursive call. However, the second iteration doesn't paginate & keeps returning the same 1000 records.
I also tried using the nextCursor value as the startWithGraphPath parameter for the second call instead. It resulted in a different response object with keys like og_object, share, id instead of data & paging.
Please help to properly obtain the taggable friends page by page, as long as 'next' value is present in the response object. Thank you.

Use the returned next endpoint (Graph path portion, including the cursor) as the new Graph path for the subsequent request, instead putting it as the parameter.

I have come across all the answers. Most of the answers are suggesting either URL based pagination or recursively calling function. We can do this from Facebook SDK itself.
var friendsParams = "taggable_friends"
// Save the after cursor in your data model
if let nextPageCursor = user?.friendsNextPages?.after {
friendsParams += ".limit(10)" + ".after(" + nextPageCursor + ")"
} else {
self.user?.friends.removeAll()
}
let requiredParams = friendsParams + "{id, name, first_name, last_name, picture.width(200).height(200)}"
let params = ["fields": requiredParams]
let _ = FBSDKGraphRequest(graphPath: "me", parameters: params).start { connection, response, error in
if connection?.urlResponse.statusCode == 200 {
print("\(response)")
// Update the UI and next page (after) cursor
} else {
print("Not able to fetch \(error)")
}
}
You can also find the example project here

Related

Facebook Friends List Swift

I am trying to run a function to see Facebook friends so users can see which are currently using the app. I have done some researching and found some older code but nothing that works with Swift 3. Here is what I have right now:
var fbRequestFriends: FBSDKGraphRequest = FBSDKGraphRequest.requestForMyFriends()
fbRequestFriends.startWithCompletionHandler{
(connection:FBSDKGraphRequestConnection!,result:AnyObject?, error:NSError!) -> Void in
if error == nil && result != nil {
print("Request Friends result : \(result!)")
} else {
print("Error \(error)")
}
}
It will not run because FBSDKGraphRequest does not have a requestForMyFriends. Does anyone know how to update this in order to work on swift 3?
I have also found this on Facebook Docs but it is all in Obj C but am having issues converting it:
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:#"/{friend-list-id}"
parameters:params
HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id result,
NSError *error) {
// Handle the result
}];
Code that you looking for is:
var fbRequestFriends: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/{friend-list-id}", parameters: [AnyHashable : Any]())
fbRequestFriends.start { (connection, result, error) in
if error == nil && result != nil {
print("Request Friends result : \(result!)")
} else {
print("Error \(error)")
}
}
It will execute the request, I do not guarantee that it will work for various reasons, for example - you need permission to ask for a friends list.

I am trying to get my friend name and ids with graph api v2.4, but data returns empty:

hi i am trying to fetch Facebook friend list who using my app when i try this function i getting empty data
my sample code
let request: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me/friends", parameters: nil, HTTPMethod: "GET")
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
print("Friends are : \(result)")
} else {
print("Error Getting Friends \(error)");
}
}
and my output is
FBSDKLog: starting with Graph API v2.4, GET requests for /me/friends should contain an explicit "fields" parameter
ID is: 964865453559288
2015-12-21 18:25:55.635[12226:218972] fb_id 964865453559288
Friends are : {
data = (
);
}
USE user_id to fetch friends.It is working fine . Try it
-(void)fetchFriendList:(NSString*)userid
{
NSString *string = [NSString stringWithFormat:#"/%#/taggable_friends",userid];
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:string
parameters:nil];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id result,
NSError *error) {
///// your results
}];
}

How to enable user to add friends via friend's username and display user's friend list in tableview with swift

I'm currently developing iOS App with Swift that users can add friends via username in one view and display user's friend list in another tableview,I'm currently using parse and I'm able to get my app to let user sign up and log in.
I want to know the code of adding friends via username and display user's friend list with parse,
I've tried looking for this solution and I got nothing but how to get friend list from Facebook which is not related to my app .
Any help is appreciated and Let me know if you need any additional information! ( sorry for my bad english).
You need to use the FBSDK for iOS in order to make a graph request for the Facebook friends list.
I don't quite understand if you want to add a "friend" that already is registered in your app or that has a Facebook account, but in any case you'll need to store your users in a data store, i believe Parse has as PFObject which you can save like this:
var appUser = PFObject(className:"AppUser")
appUser["userFullName"] = "John Doe"
appUser["userFacebookID"] = 1
appUser["userEmail"] = "j.doe#doe.com"
appUser.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
From there what you need is to associate the users, with a "Friendship" object for example, like this:
var userFriendship = PFObject(className:"Friendship")
appUser["invitedUserEmail"] = "jane.doe#doe.com"
appUser["invitingUserEmail"] = "j.doe#doe.com"
appUser["invitationStatus"] = "pending"
appUser.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
After that you can update the objet in order to change the invitation status to "accepted" or "denied, "cancel" etc.
To get a the list of user invitations and friends you need to make a ParseQuery with the arguments you're looking for, such as:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"invitingUserEmail = 'j.doe#doe.com' AND invitationStatus = 'accepted'"];
PFQuery *query = [PFQuery queryWithClassName:#"Friendship" predicate:predicate];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d friends.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
You can find a lot more in the Parse Docs here https://parse.com/docs/ios/guide

Tumblr reblog (TMTumblrSDK) return 401 error

I use TMTumblrSDK :
NSDictionary *params = #{
#"id" : 999999999999,
#"reblog_key": #"XXXXXX",
#"comment" : #"test comment",
};
[[TMAPIClient sharedInstance] reblogPost:#"test.tumblr.com"
parameters:params
callback:^(id response, NSError *error) {
...
response:
{
meta = {
msg = "Not Authorized";
status = 401;
};
response = (
);
}
OAuthConsumerKey, OAuthConsumerSecret, OAuthToken, OAuthTokenSecret is set correctly.
Methods "user/follow" "user/like" and "user/unlike" work correctly.
a similar question about android-version: Getting 401 (Not Authorized), when calling Tumblr post reblog api
also unanswered
I solved my problem.
In the "reblogPost" value necessary to transmit blog url logged in user, not the blog url, reblogged we want to do.
For example, if we want to do reblogged post of "test" user, we must not pass "test.tumblr.com". We must pass "loggedUser.tumblr.com".
It can be obtained using the method userInfo.
For example:
NSString* baseHostname;
[[TMAPIClient sharedInstance] userInfo: ^(id result, NSError* error) {
NSString * baseHostname = [result[#"user"][#"blogs"][0][#"url"] // first blog
stringByReplacingOccurrencesOfString:#"http:" withString:#""];
baseHostname = [baseHostname stringByReplacingOccurrencesOfString:#"/" withString:#""];
[[TMAPIClient sharedInstance] reblogPost: baseHostname // #"loggedUser.tumblr.com"
parameters: params
callback: ^(id response, NSError * error) {
...
}];
}];

Kinvey iOS query all users

From Kinvey documentation this is the method to use for querying users:
To query the user collection we recommend instead using
+[KCSUserDiscovery lookupUsersForFieldsAndValues:completionBlock:progressBlock:]. This
method allows you to supply a dictionary of exact matches for special
fields.
Fields for lookup:
KCSUserAttributeUsername
KCSUserAttributeSurname
KCSUserAttributeGivenname
KCSUserAttributeEmail
KCSUserAttributeFacebookId
[KCSUserDiscovery lookupUsersForFieldsAndValues:#{ KCSUserAttributeSurname : #"Smith"}
completionBlock:^(NSArray *objectsOrNil, NSError *errorOrNil) {
if (errorOrNil == nil) {
//array of matching KCSUser objects
NSLog(#"Found %d Smiths", objectsOrNil.count);
} else {
NSLog(#"Got An error: %#", errorOrNil);
}
}
progressBlock:nil];
But if I send empty dictionary, I get an error. So what to put in dictionary to get all the users?
Thank you guys, happy holidays
To get all the users, you can use the regular app data querying API.
For example,
KCSAppdataStore* store = [KCSAppdataStore storeWithCollection:[KCSCollection userCollection] options:nil];
[store queryWithQuery:[KCSQuery query] withCompletionBlock:^(NSArray *objectsOrNil, NSError *errorOrNil) {
//handle completion
} withProgressBlock:nil];
This will get a list of all the users the active user has permission to access.

Resources