How to get user interests from the native iOS Facebook SDK? - ios

I've been reading through the documentation, and I couldn't find anything. For other properties like name, id, etc, they're available in the FBGraphUser class. What I need though is the interest list for the user. I believe I have to use the FBGraphObject class, but I'm not really sure how to go about doing so. Any guidance would be very appreciated. Thanks!

me/interests is how you get the interests of the user. if you're looking for someone else, like the user's friend, then id/interests
This counts on the user being signed in
-(void)fbRequest{
[FBRequestConnection startWithGraphPath:#"me/interests" completionHandler:^(FBRequestConnection *connection,NSDictionary<FBGraphObject> *result,NSError *error){
if(!error){
NSArray *data = [result objectForKey:#"data"];
[self updateInterests:data];
}else{
}
}];
}
-(void)updateInterests:(NSArray*)interests
{
NSString *str = self.groupList.text;
for(FBGraphObject <FBGraphUser>*interest in interests) //Using FBGraphUser because it implements name though I'd love to use something else
{
str = [str stringByAppendingFormat:#"%#\n",interest.name ];
}
[self.groupList setText:str];
}
an alternative to the above method does not rely on the coincidence that graphuser has name, so here it is
-(void)updateInterests:(NSArray*)interests
{
NSString *str = self.groupList.text;
for(FBGraphObject *interest in interests) //Using FBGraphUser because it implements name though I'd love to use something else
{
str = [str stringByAppendingFormat:#"%#\n",[interest objectForKey:#"name"] ];
}
[self.groupList setText:str];
}

Related

Parsing id to NSString

When parsing API responses, sometimes I can not rely on strings being embedded in quotation marks. ID's are a good example of this, where some API's will send the numerical ID as a string while some will send it as a number.
What is a good practice when parsing such a value? If I simply parse it to an NSString like so:
NSString *myID = (NSString *)message["myID"];
I can end up with an NSString object that somehow contains (long)123.
And using stringValue would cause issues when the value is actually already sent as a string (since NSString does not have a stringValue function).
A way that works, but is somewhat ugly, is this:
id myID = (NSString *)message["myID"];
if ([myID respondsToSelector:#selector(stringValue)])
{
myID = [myID stringValue];
}
You could do something like:
id myID = message["myID"];
if ([myID isKindOfClass:[NSString class]]) { ... }
else { ... }
As long as this logic is encapsulated inside data parser and is opaque for your api users (i.e. they will always get a string) any approach is fine, e.g.:
- (NSString*)parseID:(NSDictionary*)message {
id rawID = message["myID"];
if ([rawID isKindOfClass:[NSString class]]){
return rawID;
} else if ([rawID isKindOfClass:[NSNumber class]]) {
return [(NSNumber*)rawID stringValue];
} else {
// We might still want to handle this case.
NSAssert(false, #"Unexpected id type");
return nil;
}
}
Alternative is to define stringValue in extension, so any possible objet will respond to selector:
#implementation NSString(JSONStringParsing)
- (NSString *)stringValue {
return [self copy];
}
#end
Why not just use description?
NSArray *objects = #[
#NSIntegerMin,
#NSIntegerMax,
#"123456789"
];
for (id object in objects) {
NSString *stringObject = [object description];
NSLog(#"%# -> %# | %#", [object className], [stringObject className], stringObject);
}

Way to have UITextChecker suggest learned words?

I would like to add words to the Apple Dictionary used by UITextChecker, and I am aware of the learnWords: method. It's documentation, and my experience with it, suggest that it only serves to ignore words that are learned. What I would like, and what seems obvious, would be to have learned words also provided as guesses and completions provided by the UITextChecker. Is that possible?
Here's the code I'm starting with:
NSString *newWord = [NSString stringWithFormat:#"%#", #"xyz"];
if ([UITextChecker hasLearnedWord:newWord]) {
NSLog(#"skipped %#", newWord);
} else {
[UITextChecker learnWord:newWord];
NSLog(#"learning %#", newWord);
}
A user might enter "xyj" into a search field, which would prompt this code to run:
// Fake User Input
NSString *word = #"xyj";
UITextChecker *checker = [[UITextChecker alloc] init];
NSRange range = NSMakeRange(0, word.length);
NSArray *guesses = [checker guessesForWordRange:range inString:word language:#"en_US"];
for (NSString *guess in guesses) {
if ([guess isEqualToString:#"xyz"]) {
NSLog(#"Success, iOS suggested xyz!");
}
}

how can I access friends' facebook profile picture?

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.

iOS FGallery objective c assigning string value dynamically

It is a bit complicated to explain my problem. I am using FGallery library https://github.com/gdavis/FGallery-iPhone and especially its feature to load images from URL addresses. When I hardcode the URL path it works super, but wen I pass a string variable to the class which I have created it doesn't work. I tried to debug it and it seems that everything is ok, there is a string assigned to the variable and everything, but do not show the picture. I am doing this in a loop and using ARC.
-(void) loadSoftia
{
//======================================================================================
//THIS WORKS CORRECTLY!!!
wcSofia = [[NSMutableArray alloc] init];
Webcam *s1 = [[Webcam alloc]init];
s1.description=#"Sofia";
s1.location = #"http://www.ampthillweatherstation.info/currentweather/webcamimage.jpg";
[wcSofia addObject:s1];
//======================================================================================
NSMutableString *urlGetOthersLocations =[NSMutableString stringWithFormat:#"http://%#/WebHandlers/%#", #"192.168.188.204", #"BGCam.ashx"];
ServerResponse *serverResponseOthersLocations = [HelperViewController getJsonDataFromTheServer:urlGetOthersLocations];
if(serverResponseOthersLocations.data!=nil)
{
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:serverResponseOthersLocations.data
options:NSJSONReadingMutableLeaves|NSJSONReadingMutableContainers
error:nil];
[wcSofia removeAllObjects];
Webcam *wc;
int i=0;
for (NSDictionary *locationsDic in dic){
NSString *key;
for ( key in locationsDic) {
NSLog(#"%# = %#", key, [locationsDic objectForKey: key]);
}
NSLog(#"%#", [locationsDic objectForKey:#"URL"]);
NSLog(#"%# = %#", locationsDic, [locationsDic objectForKey: locationsDic]);
NSString *url =[locationsDic objectForKey:#"URL"];
// NSLog(#"%#", url);
NSMutableString* theString = [NSString stringWithFormat:#"%i ",i];
wc = [[Webcam alloc]initWithLocation: [NSString stringWithFormat:#"%#", url] withDescription:#"description"];
wc.location = url;//DOESNT WORK!
wc.description =#"София";// theString;//[NSString stringWithFormat:#"%#", #"aa"]; // #"София";
wc.location = #"http://media.borovets-bg.com/cams/channel?channel=61";//IT WORKS BECAUSE IT IS HARDCODED
if(wcSofia!=nil)
{
[wcSofia addObject:wc];
NSLog(#"%#", wc.location);
}
i++;
}
}
}
I have commented a section of the code which works and which doesn't.
I suppose that you are not going to need the whole program, because it make requests to my local web server to get the URL addresses and descriptions, but trust me this thing works perfect.
Thank you for your help in solving that mystery.
Edit:
Complete source Code: https://dl.dropboxusercontent.com/u/46512232/FGallery.zip

Escape characters in a Dictionary before upload - Objective C

My company has an iOS app that interfaces directly with Salesforce, with one major drawback. When a user attempts to upload an illegal character, the app hangs, returns bad values, or results in some other erratic behavior.
I found a really handy piece of code out in the mystical interwebs (thanks, MailDrop), that filters a string and escapes those illegal characters with a forward slash. It then returns the value in a string, ready for upserting/querying.
One thing I'm really having trouble with is getting this to work with our application, though. Our data is stored in a dictionary and is written to in a variety of ways (querying the server, or manual input), and at various times in the application's life cycle. I'm not quite sure how to invoke this nifty 'escapeSosl' in the most efficient method. Is there a way that I can escape these characters every time I write to Core Data? What I'm most afraid of is going through the app and calling this hundreds of times.
Here is the escaping method:
- (NSString *)escapeSosl:(NSString *)src {
// from docs, these are all reserved
NSArray *reserved = [NSArray arrayWithObjects:#"\\", #"&", #"|", #"!", #"{", #"}", #"[", #"]", #"^", #"~", #"*:", #":", #"'" ,#"\"", #"+", #"-", nil];
NSMutableString *s = [NSMutableString stringWithString:src];
NSString *r;
NSEnumerator *e = [reserved objectEnumerator];
while (r = [e nextObject])
[s replaceOccurrencesOfString:r withString:[NSString stringWithFormat:#"\\%#", r] options:NSLiteralSearch range:NSMakeRange(0, [s length])];
return s;
}
What I find complicated is the timing of these escapings, and how to apply that to each situation. For instance, the app queries Salesforce for an Account using a location that was either manually entered or found via reverse geocoding. Here is an example of the app requesting data from the Salesforce Server:
-(void)checkServerForLeadMatchingAddressOnAccount:(SFAccount *)account {
currentAccount = account;
//Parse the account location data, removing the last word in the `street` object
NSString *street = account.shippingStreetAddress;
NSMutableArray *streetArray = [[street componentsSeparatedByString:#" "] mutableCopy];
[streetArray removeLastObject];
street = [streetArray componentsJoinedByString:#" "];
street = [street stringByAppendingString:#"_%"];
NSString *city = account.shippingCity;
NSString *state = account.shippingState;
NSString *zip = account.shippingZIP;
//Check for a matching lead on the server. User the callback methods to proceed (either create new data on the server or download to the device
NSLog(#"is connected: %i", self.isConnectedToServer);
if (self.isConnectedToServer){
requestCheckForLead = [[SFRestAPI sharedInstance] requestForQuery:[NSString stringWithFormat:#"SELECT ID, Company, Name, Street, City, State, PostalCode, Phone FROM Lead WHERE PostalCode = '%#' AND Street LIKE '%#' AND City = '%#' AND State = '%#'", zip, street, city, state]];
[[SFRestAPI sharedInstance] send:requestCheckForLead delegate:self];
openTasks++;
} else {
NSLog(#"I can't connect");
[self.serverDelegate serverObjectManager:self communicationSuccessful:NO withResponse:#"Could not connect to the server."];
}
Another area where I might escape characters is right before initiating an upload to the server. There are a couple things that get uploaded, including an Account, the Account's Contact (1:1 rel.), the Account's Opportunity (1:1 rel.), and an Opportunity's Current Service Levels (1:many rel).
Here is an example of the Contact associated with an Account - it uses both Strings and dictionary references, but has some additional logic for parsing firstName from lastName. I'd like to escape the data in a way that I do not need to worry about the timing of these manipulations.
NSMutableDictionary *contactDict = [NSMutableDictionary new];
if (myAccount.contact.email) {
[contactDict setObject:myAccount.contact.email forKey:#"Email"];
} else {
[contactDict setObject:#"" forKey:#"Email"];
}
if (myAccount.contact.name) {
//Split name in two
NSArray *nameArray = [myAccount.contact.name componentsSeparatedByString:#" "];
NSString *firstName = [nameArray objectAtIndex:0];
NSString *lastName = [nameArray lastObject];
[contactDict setObject:firstName forKey:#"firstName"];
[contactDict setObject:lastName forKey:#"lastName"];
} else {
[contactDict setObject:#"" forKey:#"firstName"];
[contactDict setObject:#"" forKey:#"lastName"];
}
if (myAccount.contact.phone){
[contactDict setObject:myAccount.contact.phone forKey:#"Phone"];
} else {
[contactDict setObject:#"" forKey:#"Phone"];
}
updateContactRequest = [[SFRestAPI sharedInstance] requestForUpdateWithObjectType:#"Contact" objectId:myAccount.createdContactID fields:contactDict];
[[SFRestAPI sharedInstance] send:updateContactRequest delegate:self];
So this may seem like a bit of a large question, but does anyone have some pointers as to how I could escape characters in these various dictionaries, using something similar to the 'escapeSosl' code I included above, whenever things are written to core data?
In this line you build your query
requestCheckForLead = [[SFRestAPI sharedInstance] requestForQuery:[NSString stringWithFormat:#"SELECT ID, Company, Name, Street, City, State, PostalCode, Phone FROM Lead WHERE PostalCode = '%#' AND Street LIKE '%#' AND City = '%#' AND State = '%#'", zip, street, city, state]];
instead of passing street as the parameter pass [self escapeSosl:street] and so on for the other params.

Resources