Fetching user data from Facebook on Xcode - xcode

I am trying to develop a simple app, which, retrieves data from Facebook, when the user connects to it.
After reading Facebook's example about how to retrieve User's photos and User's names, I just want to get information such as gender, city, e-mail, and date of birth, for example.
The following part, is where I got stuck:
- (void)populateUserDetails
{
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:
^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
self.userNameLabel.text = user.name;
self.userProfileImage.profileID = user.id;
}
}];
}
}
My questions are:
Should I make a dictionary with all this data? (gender, city, e-mail, etc.)
-Also, I'm using the storyboard, can I use labels to all those data as Facebook's tutorial states, for the username?
I read in a couple of places that the method requestForMe isn't the appropriate one for the other type of data I am looking for. What would be the method for my requests?

First you must ask user for permissions to access his gender, email, city ...
You make a array with required permissions and add it to the openActiveSessionWithReadPermissions: method
NSArray *permissions = [[NSArray alloc] initWithObjects:#"user_birthday",#"user_hometown",#"user_location",#"email",#"basic_info", nil];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
Then make a request like this to get informations you wanted
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"%#", [result objectForKey:#"gender"]);
NSLog(#"%#", [result objectForKey:#"hometown"]);
NSLog(#"%#", [result objectForKey:#"birthday"]);
NSLog(#"%#", [result objectForKey:#"email"]);
}];
I hope i resolved your problem.

Related

Inconsistent results creating bidirectional relationship between PFUser and PFObjects

I am attempting to create a bidirectional relationship between a PFUser and some PFObjects using PFRelations.
First I create a Posting and save that in the background.
And in the completion block I add the new posting in the PFUser by appending to the list of Postings that are already related to this User and re-save the User with a synchronous save call.
The Posting is always saved correctly with the correct Relation to the User, however, the Relation back to the Posting in the User only works intermittently. Stepping through the code results in the correct outcome each time which leads me to believe it's some sort of race condition. What would cause this behavior? Is there a better way to achieve the desired relationships?
PFUser *currentUser = [PFUser currentUser];
PFObject *posting = [PFObject objectWithClassName:#"Postings"];
__weak HLReviewPostItemViewController *myself = self;
posting[#"title"] = self.createdItem[#"title"];
posting[#"price"] = self.createdItem[#"price"];
posting[#"owner"] = currentUser;
[posting saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
PFGeoPoint *currentGeoPoint = [myself.locationManager getCurrentGeoPoint];
[currentUser setObject:currentGeoPoint forKey:#"geoPoint"];
PFRelation *postingsForUser = [currentUser relationForKey:#"postings"];
[postingsForUser addObject:posting];
NSError *error;
[currentUser save:&error];
if (!error) {
[myself.dataManager fetchLocalUsers];
} else {
NSLog(#"Error saving Posting in user relation: %#", error);
}
} else {
NSLog(#"Error saving Posting: %#", error);
}
}];
When you save the posting, because the posting has a column that stores the owner, the owner - the parent, also gets saved automatically - very nice feature of Parse.
When you step through the code automatic save is executed and finished before your next re-save. But when you run the code, there is no guarantee which save to PFUser object would occur first.

Compare UITextField with PFQuery of parse.com

I have a small problem .. I hope you can help me ...
In my app I'm using Parse.com for data management.
I have a ViewController that contains a TextField called "Email".
With a query parse.com call all the registered user app and their email. Now I would like to try to compare the values of the textField and those of the query .. Let me give an example ..
The user enters their email in the textField but if this email is already present in the archive of the users (of course taken by the query parse.com) shows an alert that warns him that the Supplied in textField is already existing in parse.com.
I tried to do this but it does not always recognize the email in query..dove am I doing wrong?
P.S. the textField is not in viewController Main but is in another
ViewController called generalData.
-(void)query {
PFQuery *totalUser = [PFUser query];
[totalUser findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
[array addObject:object];
NSLog(#"%#", [object objectForKey:NPUserKey_EMAIL]);
// NSStrings
email = generalData.emailTextField.text;
compareEmail = [object objectForKey:NPUserKey_EMAIL];
}
}
}];
}
- (IBAction)presentNextViewController:(id)sender {
if ([generalData.emailTextField.text isEqualToString:compareEmail]) {
NSString *stringError = [NSString stringWithFormat:#"L'email %# è gia presente nei nostri archivi.",email];
NPUMessageView *alertMessage;
alertMessage= [[NPUMessageView alloc] showViewWithMessage:stringError withBackgroundColor:SECONDARY_COLOR];
[self.view addSubview:alertMessage];
[alertMessage showAnimatedView];
NSLog(#"email found in archive");
}
else {
NSInteger index = [controllersContainer indexOfObject:self.destinationViewController];
index = MIN(index+1, [controllersContainer count]-1);
[self presentCurrentViewController:self.currentViewController withPage:index];
}
}
I think you are getting ahead of yourself a little bit. Parse automatically checks for duplicate emails when you try to sign up a new user. Let the user enter their email into the field, and when they try to create the account, display the error Parse returns from the signup method, and let them try again!
https://www.parse.com/docs/ios_guide#users-signup/iOS

Accessing 'Internet Accounts' programmatically

I'm trying to access the 'accounts' that are stored in the Internet Accounts area on the system settings on OSX. I'm aware of the 'ACAccount' library, but this only really seems to be of any use for Social integration, for example Facebook/Twitter, what i would like is to be able to detect that you have an Exchange account there and open up certain features within an app. But i'm guessing i'll need to get my users to re-enter their details in my app?
I did try and use it, however i get an empty array.
ACAccountStore *store = [[ACAccountStore alloc] init];
NSArray *accounts = [store accounts]; //This is empty
Does anyone know if i'm missing something, or if it's not possible? Thanks!
Edit
I have gained access to the Twitter account for example, but it's not returned in the Accounts list, i had to request permission first. Which makes sense. However, i still see no way of getting access to the Exchange account.
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:
ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil
completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
NSArray *arrayOfAccounts = [account
accountsWithAccountType:accountType];
}
}];

Parameters are always null when AFJSONRequestSerializer is used for a POST in AFNetworking

I'm writing a REST API by using SlimFramework in server side and AFNetworking in client side.
I'd like to add a value in Header for Authorization so that I'm using AFJSONRequestSerializer before the POST. Here is my code:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:self.apikey forHTTPHeaderField:#"Authorization"];
[manager POST:url parameters:#{REST_PARAM_USERID: userId}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
But the failure callback is always called. I found that's because the parameters I passed to server are always null although they're not null when I debugged in my Xcode. When I comments out the requestSerializer then my server works well.I don't know what's the reason. Can anybody help? Thanks
When you use AFJSONRequestSerializer, your parameters will always be serialized as JSON in the body of the HTTP request. If your server is not expecting JSON, then you should either reconfigure your server, or not use AFJSONRequestSerializer.
If, for some reason, you want to send some parameters through normal URL encoding, and others through JSON, you'll need to manually append them to your URL like so:
NSString *urlWithParams = [NSString stringWithFormat:#"%#?%#=%#", url, REST_PARAM_USERID, userId"];
[manager POST:urlWithParams parameters:#{#"some other" : #"params"}
success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];

Uploading a file with POST using AFNetworking

So I'm trying to upload an XML file to a server with POST using AFNetworking.
So using example code from their site I have this set up. When it runs, something is uploaded to the server (or at least it leaves my computer). I can monitor the upload, when the upload is finished, the server recognizes that it completed and goes to load the file, but it loads an old XML. So its connecting properly to the server, but I'm not sure why the file upload isn’t working correctly. Also I just want to send the file, the server doesn’t need any headers or parameters etc.
So I'm wondering if I’ve stored the data correctly? Or if I'm not sending it the server properly or what? Any suggestions would be helpful
NSData *iTunesXMLData = [NSData dataWithContentsOfFile:filePath];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
/* NSMutableURLRequest *request =[httpClientmultipartFormRequestWithMethod:#"POST"
path:#"/upload.php?id=5" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFileData:iTunesXMLData name:#"iTunes Music Library" fileName:#"iTunes Music Library.xml" mimeType:#"application/xml"];
}];*/
//I tried this way also, both did the same thing
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:#"POST" path:#"/upload.php?id=5" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
[formData appendPartWithFormData:iTunesXMLData name:#"iTunes Music Library"];
}];`
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];`
NSLog(#"Operation: %#", operation);
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(#"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];
Have you tried to catch the success/failure of the operation? Try this after setUploadProgressBlock:
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// Operation ended successfully
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Something happened!
NSLog(#"ERROR: %#, %#", operation, error);
// Here you can catch operation.responseString to see the response of your server
}];
This is an easy way to know what your server returned. If something uploads to your server, double check that you're getting the right file. AFAIK, your AFNetwork seems ok.

Resources