How can we get the complete list of friends, currently I am using
[FBRequestConnection startForMyFriendsWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
// Do stuff
} else {
// Throw error
}
In the response, we get a paging and the next url. Does anyone know how we can loop through the next url's and get the complete list of friends ?
Response has
paging = {
next = "https://graph.facebook.com/1301xxxxxx/friends?fields=id,name,username,first_name,last_name&format=json&access_token=BAAFjJBl9zZBABALFxcbix0aNe0NFOfW8mHCU4ntPaxwooYVo1L6fOWgNTMTZBqLHfxjrWBOXNLjcCwEbkBgZAJX22Ec9PlatgHP9GfjVEWyxk0qGtxxxxxxxxxx&limit=5000&offset=5000&__after_id=10000xxxxxx";
};
Thanks in advance
At first you need to get link on next, you need to extract offset and __after_id parameters,according to iPhone parsing url for GET params you will get dictionary with parameters:
//put here your string with parameters
NSString* next = #"https://graph.facebook.com/1301xxxxxx/friends?fields=id,name,username,first_name,last_name&format=json&access_token=BAAFjJBl9zZBABALFxcbix0aNe0NFOfW8mHCU4ntPaxwooYVo1L6fOWgNTMTZBqLHfxjrWBOXNLjcCwEbkBgZAJX22Ec9PlatgHP9GfjVEWyxk0qGtxxxxxxxxxx&limit=5000&offset=5000&__after_id=10000xxxxxx";
NSArray * pairs = [next componentsSeparatedByString:#"&"];
NSMutableDictionary * kvPairs = [NSMutableDictionary dictionary];
for (NSString * pair in pairs) {
NSArray * bits = [pair componentsSeparatedByString:#"="];
NSString * key = [[bits objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString * value = [[bits objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[kvPairs setObject:value forKey:key];
}
You can get correct parameters by kvPairs[#"__after_id"] and kvPairs[#"offset"]
Next step create add this parameters to your original request, in original request offset and after id should be nil, and you need to filter this situation, if you will do all correct, you will be able to call your ethos recursively
Related
I am using AFNetworking to retrieve information about the weather for a specific location, e.g:
http://api.openweathermap.org/data/2.5/weather?q={New%20York%20City}
I am using the AFNetworking framework but I am having the problems parsing some objects of the JSON.
If I have an NSDictionary with the MAIN object information from the JSON:
NSDictionay *main = [responseObject objectForKey:#"main"];
If I log the main NSDictionary I will get the following valid output:
"main":{
"temp":296.78;
"pressure":1011;
"humidity":69;
"temp_min":293.15;
"temp_max":299.82
};
Although if I create a NSDictionary containing the weather object I will get the following information whenever logging it to the console:
NSDictionay *weather = [responseObject objectForKey:#"weather"];
"weather":(
{
"id":801;
"main":"Clouds";
"description":"few clouds";
"icon":"02d"
}
);
The parsed information contains ( brackets instead of [ from the original response. This does not allow me to correctly access the inside attributes of the weather object.
Summing up, I am able to access all the inside variables of the MAIN object, but I cannot access the attributes of the Weather object (e.g access the icon attribute).
Can someone help me with this ?
Thank you,
You calling your service as below.
NSString *query = #"http://api.openweathermap.org/data/2.5/weather?q={New%20York%20City}";
NSLog(#"%#",query);
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error] : nil;
Now print Response :
NSLog(#"weather==%#",[results objectForKey:#"weather"]);
NSLog(#"description==%#",[[[results objectForKey:#"weather"] objectAtIndex:0] objectForKey:#"description"]);
NSLog(#"icon==%#",[[[results objectForKey:#"weather"] objectAtIndex:0] objectForKey:#"icon"]);
NSLog(#"id==%#",[[[results objectForKey:#"weather"] objectAtIndex:0] objectForKey:#"id"]);
NSLog(#"main==%#",[[[results objectForKey:#"weather"] objectAtIndex:0] objectForKey:#"main"]);
Your Response is :
whwather==(
{
description = "sky is clear";
icon = 01d;
id= 800;
main= Clear;
}
)
description== "sky is clear";
icon == 01d;
id == 800;
main == Clear;
I need to access friends' profile pictures to display them in my game leaderboard. Most of the links to posts I found here on stackoverflow do not exist anymore. How can I access the profile pictures in a way similar to how I accessed the scores and names in the code below.
-(void)getLeaderboardInfo
{
[FBRequestConnection startWithGraphPath:[NSString stringWithFormat:#"%llu/scores?fields=score,user", kuFBAppID] parameters:nil HTTPMethod:#"GET" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (result && !error)
{
int index = 0;
for (NSDictionary *dict in [result objectForKey:#"data"])
{
NSString *name = [[[[dict objectForKey:#"user"] objectForKey:#"name"] componentsSeparatedByString:#" "] objectAtIndex:0];
NSString *strScore = [dict objectForKey:#"score"];
// how do I get the objectforkey representing the image?
m_pLeaderboardEntries[index].pFriendName.text = [NSString stringWithFormat:#"%d. %#", index+1, name];
m_pLeaderboardEntries[index].pFriendScore.text = [NSString stringWithFormat:#"Score: %#", strScore];
// how do I add the image to my leaderboard entries?
index++;
if (index>5) {
break;
}
}
}
}];
}
The LeaderboardInstance
struct LeaderboardboardInstance
{
__unsafe_unretained UILabel *pFriendName;
__unsafe_unretained UILabel *pFriendScore;
__unsafe_unretained UIImage *profilePicture;
};
Also,
struct LeaderboardboardInstance m_pLeaderboardEntries[m_kuLeaderboardSize];
Add this to your list of fields
picture.type(large)
In the result object you should then have a dictionary called picture which contains image info including the url of the users image
Assuming you have a Facebook user logged in and the friend's Facebook ID, this is the way to go:
NSString *imageUrl = [NSString stringWithFormat:#"http://graph.facebook.com/%#/picture?type=large", friendID];
Then you can download the image using NSURLConection or whatever library you want.
I am looking for two API calls in Youtube Data API V3.
First I want to get the Channel ID by specifying the name of the channel.
Once I have the Channel ID I want to get n number of videos from that channel.
I am looking for the API calls that I have to make.
Also, does anyone know if there's a chance that channel or video IDs may change at some point? If they can change for the same video/channel then I should not hardcode the ID's in my code.
Thanks
For total newbies who want a running example : consider a function that will help understand the entire cycle of fetch,parse,display etc and bring youtube channel's videos to your tableview specifically. im not writing the tableview part here
-(void)initiateRequestToYoutubeApiAndGetChannelInfo
{
NSString * urlYouCanUseAsSample = #"https://www.googleapis.com/youtube/v3/search?key={YOUR_API_KEY_WITHOUT_CURLY_BRACES}&channelId={CHANNEL_ID_YOU_CAN_GET_FROM_ADDRESS_BAR_WITHOUT_CURLY_BRACES}&part=snippet,id&order=date&maxResults=20";
NSURL *url = [[NSURL alloc] initWithString: urlYouCanUseAsSample];
// Create your request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// Send the request asynchronously remember to reload tableview on global thread
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// Callback, parse the data and check for errors
if (data && !connectionError) {
NSError *jsonError;
NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
if (!jsonError) {
// better put a breakpoint here to see what is the result and how it is brought to you. Channel id name etc info should be there
NSLog(#"%#",jsonResult);
/// separating "items" dictionary and making array
//
id keyValuePairDict = jsonResult;
NSMutableArray * itemList = keyValuePairDict[#"items"];
for (int i = 0; i< itemList.count; i++) {
/// separating VIDEO ID dictionary from items dictionary and string video id
id v_id0 = itemList[i];
NSDictionary * vid_id = v_id0[#"id"];
id v_id = vid_id;
NSString * video_ID = v_id[#"videoId"];
//you can fill your local array for video ids at this point
// [video_IDS addObject:video_ID];
/// separating snippet dictionary from itemlist array
id snippet = itemList[i];
NSDictionary * snip = snippet[#"snippet"];
/// separating TITLE and DESCRIPTION from snippet dictionary
id title = snip;
NSString * title_For_Video = title[#"title"];
NSString * desc_For_Video = title[#"description"];
//you can fill your local array for titles & desc at this point
// [video_titles addObject:title_For_Video];
// [video_description addObject:desc_For_Video];
/// separating thumbnail dictionary from snippet dictionary
id tnail = snip;
NSDictionary * thumbnail_ = tnail[#"thumbnails"];
/// separating highresolution url dictionary from thumbnail dictionary
id highRes = thumbnail_;
NSDictionary * high_res = highRes[#"high"];
/// separating HIGH RES THUMBNAIL IMG URL from high res dictionary
id url_for_tnail = high_res;
NSString * thumbnail_url = url_for_tnail[#"url"];
//you can fill your local array for titles & desc at this point
[video_thumbnail_url addObject:thumbnail_url];
}
// reload your tableview on main thread
//[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
performSelectorOnMainThread:#selector(reloadInputViews) withObject:nil waitUntilDone:NO];
// you can log all local arrays for convenience
// NSLog(#"%#",video_IDS);
// NSLog(#"%#",video_titles);
// NSLog(#"%#",video_description);
// NSLog(#"%#",video_thumbnail_url);
}
else
{
NSLog(#"an error occurred");
}
}
}];
}
First call is a search.list with setting q as channel name and type="channel".
Second one is calling channels.list with that id and get the playlistId of the uploaded videos list.
Third is the playlistItems.list to list videos under that playlist.
So I was working on pulling photos from user's Facebook album and for some reason NSDictionary doesn't throw an exception when nil is inserted.
I've tested it on a real device and on iOS simulator (both iOS 7).
Maybe debugger crashes, maybe it's Facebook SDK bug.
Anyway, I'm ready to listen to your opinion.
UPDATE: One more thing I forgot to mention. In debugger, after inserting nil object in dictionary, debugger itself continues program execution. And I'm not even pressing the buttong "Continue program execution".
Here's the snippet
- (void)downloadAlbumsWithCompletionBlock:(void (^)(NSArray *albums, NSError *error))completionBlock;
{
[FBRequestConnection startWithGraphPath:#"/me/albums"
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (error)
{
NSLog(#"%#", error.localizedDescription);
completionBlock(nil, error);
}
else
{
NSMutableArray *data = [result objectForKey:#"data"];
NSMutableArray *albums = [NSMutableArray new];
for (NSMutableDictionary *dict in data)
{
NSString *albumID = dict[#"id"];
NSString *coverPhotoID = dict[#"cover_photo"];
// coverPhotoID gets nil and then successfully gets put in NSDictionary
// You can just write "NSString *coverPhotoID = nil;".
NSString *description = dict[#"description"];
NSString *name = dict[#"name"];
NSDictionary *album = #{#"album_id": albumID,
#"album_cover_photo_id": coverPhotoID,
#"album_description": description,
#"album_name": name };
// Here an exception should be thrown but for some reason
// we just quit out of the method. Result would be the same if we put
// empty "return;" statement.
// If we explicitly put nil, like
// #"album_cover_photo_id": nil
// we get compiler error.
[albums addObject:album];
}
completionBlock(albums, nil);
}
}];
}
You wrote:
// Here an exception should be thrown but for some reason
// we just quit out of the method. Result would be the same if we put empty "return;" statement.
Most likely the exception is caught somewhere. Try putting a breakpoint on Objective-C exception throws (In Xcode, go to the Breakpoint tab, click + in the bottom left corner and select Add Exception Breakpoint. Make sure the parameters are set to Objective-C exception and break On Throw).
You claim that
NSString *albumID = dict[#"id"];
NSString *coverPhotoID = nil;
NSString *description = dict[#"description"];
NSString *name = dict[#"name"];
NSDictionary *album = #{#"album_id": albumID,
#"album_cover_photo_id": coverPhotoID,
#"album_description": description,
#"album_name": name };
doesn't crash your app.
Honestly, I don't believe it. Either you're trolling or you're misinterpreting whats happening.
As the first line of your for cycle log the dict dictionary:
NSLog(#"dict var: %#", dict);
Does dict contains the key album_cover_photo_id?
If you get something like
"album_cover_photo_id" : null
then NSString *coverPhotoID = dict[#"cover_photo"] is assigning an NSNull instance to coverPhotoID. In that case the app doesn't crash because an NSNull instance is not nil.
NSString *coverPhotoID = nil;
is different then
NSString *coverPhotoID = [NSNull null];
It's very common for servers to return nulls in JSON instead of omitting the key (server people are weird).
You can also log album after you create it
NSLog(#"album var: %#", album);
And if you are 100 % sure you're adding a nil to a dictionary, take it to the Apple developer forum. I bet they'd love to know about that bug.
I hope this helps you in some way.
Whats is the best way to parse this out?
String:
UMversion=2.9&UMstatus=Approved&UMauthCode=152058&UMrefNum=59567592&UMavsResult=Address%3A%20Match%20%26%205%20Digit%20Zip%3A%20Match&UMavsResultCode=YYY&UMcvv2Result=Match&UMcvv2ResultCode=M&UMresult=A&UMvpasResultCode=&UMerror=Approved&UMerrorcode=00000&UMcustnum=&UMbatch=1&UMbatchRefNum=91016&UMisDuplicate=N&UMconvertedAmount=&UMconvertedAmountCurrency=840&UMconversionRate=&UMcustReceiptResult=No%20Receipt%20Sent&UMprocRefNum=&UMcardLevelResult=A&UMauthAmount=10&UMfiller=filled
I get this back from the web service as one big long string. Each of the variables are listed then they have a = sign then what I need to populate the variable with.
I need to get all of this data into variables to check them.
So, how should I go about breaking it down.
Use this kind of code:
NSArray* components = [veryLongString componentsSeparatedByString:#"&"]; // array of strings like "x=y"
NSMutableDictionary* parsedResult = [NSMutableDictionary new];
for (NSString* keyValuePair in components) {
NSArray* keyAndValue = [keyValuePair componentsSeparatedByString:#"="];
NSString* key = keyAndValue[0];
NSString* value = (keyAndValue.count>1) ? keyAndValue[1] : nil;
// remove percent escapes in case we have URL-encoded characters in the value like '%20' and the like
parsedResult[key] = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ?: [NSNull null];
}
NSLog(#"dictionary of parameters: %#", parsedResult);
You will end up with a dictionary containing the keys and values extracted from your string.
NSString* firstPass = [sourceString stringByReplacingOccurrencesOfString:#"&" withString:#"\",\""];
NSString* secondPass = [firstPass stringByReplacingOccurrencesOfString:#"=" withString:#"\":\""];
NSString* grandFinale = [NSString stringWithFormat:#"{\"%#\"}"];
NSData* jsonSource = [grandFinale dataUsingEncoding:NSUTF8Encoding];
NSError* error = nil;
NSDictionary* theBiggie = [NSJSONSerialization JSONObjectWithData:jsonSource options:0 error:&error];
I think NSJSONSerialization will automagically fix up the percent encoding. If not, run grandFinale through stringByRemovingPercentEncoding.