Objective C: Detect number of Facebook invites - objective-c

I'm trying to detect how many invites the user has sent while logged into their Facebook account. For example, I'm giving the user an option to purchase an item by inviting 3 friends to use the iOS application. If they invite 3, they are rewarded with the item. I'm really stuck on this one. Any help would be great and much appreciated!

I actually found code snippet for this after much research. I can't remember if it was on here or not, but here it is.
- (IBAction)inviteFacebookFriendsButton:(id)sender
{
// FBSample logic
// if the session is open, then load the data for our view controller
if (!FBSession.activeSession.isOpen)
{
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:NO
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
} else if (session.isOpen) {
}
}];
}
MouseInTheHouseAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
if (appDelegate.session.isOpen)
{
NSMutableDictionary *postVariablesDictionary = [[NSMutableDictionary alloc] init];
[postVariablesDictionary setObject:#"Come play Mouse in the House with me!" forKey:#"message"];
[postVariablesDictionary setObject:#"Invite Friends" forKey:#"title"];
[FBWebDialogs presentDialogModallyWithSession:[FBSession activeSession] dialog:#"apprequests" parameters:postVariablesDictionary handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error)
{
if (error)
{
// Case A: Error launching the dialog or sending request.
NSLog(#"Error sending request.");
}
else
{
if (result == FBWebDialogResultDialogNotCompleted)
{
// Case B: User clicked the "x" icon
NSLog(#"User canceled request.");
}
else
{
NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern:#"to%5B\\d+%5D=(\\d+)"
options:NSRegularExpressionCaseInsensitive
error:NULL];
NSArray * matches = [regex matchesInString:resultURL.absoluteString
options:0
range:(NSRange){0, resultURL.absoluteString.length}];
NSMutableArray * ids = [NSMutableArray arrayWithCapacity:matches.count];
for (NSTextCheckingResult * match in matches)
{
[ids addObject:[resultURL.absoluteString substringWithRange:[match rangeAtIndex:1]]];
}
NSLog(#"Number of friends invited: %lu", (unsigned long)ids.count);
}
}
}];
}
}

Related

iOS8 Touch ID & Passcode

i using this code in iOS 8 for security and uses touch ID
- (IBAction)authenticateButtonTapped{
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = #"Authenticate using your finger\r Scan Your Finger Now";
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL succes, NSError *error) {
if (succes) {
[self showMessage:#"Authentication is successful" withTitle:#"Success"];
NSLog(#"User authenticated");
} else {
switch (error.code) {
case LAErrorAuthenticationFailed:
[self showMessage:#"Authentication is failed" withTitle:#"Error"];
NSLog(#"Authentication Failed");
break;
case LAErrorUserCancel:
[self showMessage:#"You clicked on Cancel" withTitle:#"Error"];
NSLog(#"User pressed Cancel button");
break;
case LAErrorUserFallback:
[self showMessage:#"You clicked on \"Enter Password\"" withTitle:#"Error"];
NSLog(#"User pressed \"Enter Password\"");
[self copyMatchingAsync];
break;
default:
[self showMessage:#"Touch ID is not configured" withTitle:#"Error"];
NSLog(#"Touch ID is not configured");
break;
}
NSLog(#"Authentication Fails");
}
}];
} else {
NSLog(#"Can not evaluate Touch ID");
[self showMessage:#"Can not evaluate TouchID" withTitle:#"Error"];
}
}
after for use the passcode system i copy this code from apple example
- (void)copyMatchingAsync
{
NSDictionary *query = #{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: #"SampleService",
(__bridge id)kSecReturnData: #YES,
(__bridge id)kSecUseOperationPrompt: NSLocalizedString(#"AUTHENTICATE_TO_ACCESS_SERVICE_PASSWORD", nil)
};
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
CFTypeRef dataTypeRef = NULL;
NSString *msg;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)(query), &dataTypeRef);
if (status == errSecSuccess)
{
NSData *resultData = ( __bridge_transfer NSData *)dataTypeRef;
NSString * result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
msg = [NSString stringWithFormat:NSLocalizedString(#"RESULT", nil), result];
} else {
}
});
}
-(void) showMessage:(NSString*)message withTitle:(NSString *)title
{
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
its work great and rapid for fingerprint but the passcode system can't show and dosen't work. and i received "ERROR_ITEM_NOT_FOUND" = "error item not found";
this apple link https://developer.apple.com/library/ios/samplecode/KeychainTouchID/Introduction/Intro.html
but i can't good understand
Sorry to tell you but you can't do that.
You are mixing access control with keychain access, You don't have access to the user passcode.
using SecItemCopyMatching is possible if you added a resource with SecItemAdd using the same attributes (the contents of "query")
"ERROR_ITEM_NOT_FOUND" = "error item not found" show no item in keychain.
I also saw the Apple sample code "KeychainTouchID" as you said above.
iOS8's new feature make the developer can use the iPhone user's passcode & Touch ID for authentication.
You have to "Add Item" firstly, and then call "Query for Item".
If you want more convenient solution, maybe you can use SmileTouchID.
It is a library for integrate Touch ID & Passcode to iOS App conveniently that even support for iOS7 and the device that cannot support Touch ID.
You just need a few line of code and get what you want.
if ([SmileAuthenticator hasPassword]) {
[SmileAuthenticator sharedInstance].securityType = INPUT_TOUCHID;
[[SmileAuthenticator sharedInstance] presentAuthViewController];
}

What does the filed "installed" in Facebook graph "me/friends" specify

I am using the code bellow to get the list of all of users friends and check how many of them have installed the app so i can show their scores, and unlock some content for the user.
I can't find solid info about the field installed which seams to be perfect for this case.(If it specifies the user has installed the app which made the request :) )
[FBRequestConnection startWithGraphPath:#"me/friends"
parameters: #{ #"fields" : #"id,installed"}
HTTPMethod:nil
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (!error) {
// Get the result
NSArray *resultData = result[#"data"];
// Check we have data
if ([resultData count] > 0) {
// Loop through the friends returned
for (NSDictionary *friendObject in resultData) {
// Check if devices info available
if (friendObject[#"installed"]) {
//Do some work if user has installed my game
}
}
}
}
}];
-(void)FBFriendList
{
if (!FBSession.activeSession.isOpen)
{
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil allowLoginUI:YES completionHandler:^(FBSession *session,FBSessionState state, NSError *error)
{
if (error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:error.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else if(session.isOpen)
{
[self FB_Common_Friend];
}
}];
return;
}
}
-(void)FB_Common_Friend
{
FBRequest *request = [FBRequest requestWithGraphPath:#"me/friends" parameters:#{#"fields":#"name,installed,first_name,picture"} HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
NSLog(#"%#",result);
int count = 0;
NSMutableArray *frnd_arr = [result objectForKey:#"data"];
for (int i = 0; i < [frnd_arr count]; i++)
{
if([[[frnd_arr objectAtIndex:i] objectForKey:#"installed"] boolValue])
{
count++;
}
}
app.fb_frnd_count = count;
}];
}

NSJSONSerialization handle returning array or dictionary

I am making a call to twitters API to load some tweets for a specific section of my app.
A small chunk of users are reporting a crash when loading the tweets view, while the rest have no problem at all.
I have submitted the code to Apple Tech Support and they responded letting me know that NSJSONSerialization can sometimes return a NSArray or NSDictionary.
Obviously it will throw an error is objectAtIndex: is called on an NSDictionary object, which I believe is the culprit for all of my users.
The partial solution is to detect if it is an Array or NSDictionary.
Here is where I am at now:
id feedData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonError];
if ([feedData isKindOfClass:[NSArray class]]) {
//Is array
} else if ([feedData isKindOfClass:[NSDictionary class]]) {
//is dictionary
}
I basically need an NSArray every single time. So in the is array block, I basically just use the feedData, but in NSDictionary, how can I convert it to an NSArray that will match the structure I need.
Honestly the biggest issue is that I cannot see what the NSDictionary structure looks like because none of my testing devices or simulator return the NSDictionary data, they all return an NSArray.
Here is what the entire getUserFeed method that sends the request to twitter looks like:
// Get the twitter feed
NSURL *requestURL = [NSURL URLWithString:TW_API_TIMELINE];
// Set up proper parameters
NSMutableDictionary *timelineParameters = [[NSMutableDictionary alloc] init];
[timelineParameters setObject:kNumTweets forKey:#"count"];
[timelineParameters setObject:#"1" forKey:#"include_entities"];
// Create the Social Request
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodGET URL:requestURL parameters:timelineParameters];
postRequest.account = self.delegate.userAccount;
// Perform the request
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
// Check if we reached the reate limit
if ([urlResponse statusCode] == 429) {
// Rate limit reached
// Display an alert letting the user know we have hit the rate limit
UIAlertView *twitterAlert = [[UIAlertView alloc] initWithTitle:kRateLimitTitle
message:kRateLimitMessage
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[twitterAlert show];
// Stop animating the pull to refresh if it is animating
[self.feedTableView.pullToRefreshView stopAnimating];
return;
}
// Check if there was an error
if (error) {
NSLog(#"Error: %#", error.localizedDescription);
// Stop animating the pull to refresh if it is animating
[self.feedTableView.pullToRefreshView stopAnimating];
return;
}
// Check if there is some response data
if (responseData) {
NSError *jsonError = nil;
id feedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&jsonError];
if ([feedData isKindOfClass:[NSArray class]]) {
//Is array
NSLog(#"It's an Array");
} else if ([feedData isKindOfClass:[NSDictionary class]]) {
//Is dictionary
NSLog(#"It's a Dictionary");
} else {
//is something else
}
if (!jsonError) {
[self gatherTweetsFromArray:feedData];
} else {
// Stop animating the pull to refresh if it is animating
[self.feedTableView.pullToRefreshView stopAnimating];
// Alert the user with the error
UIAlertView *twitterAlert = [[UIAlertView alloc] initWithTitle:kErrorTitle
message:kErrorMessage
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[twitterAlert show];
}
} else {
// Stop animating the pull to refresh if it is animating
[self.feedTableView.pullToRefreshView stopAnimating];
// Alert the user with the error
UIAlertView *twitterAlert = [[UIAlertView alloc] initWithTitle:kErrorTitle
message:kErrorMessage
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[twitterAlert show];
}
});
}];
This is a MAJOR bug and I need to squash it, so any ideas or information will be greatly appreciated! Thank you!

Preventing UIView from switching before UIAlertView appears with Parse (Form not Complete, Logout Yes/No, etc)

I am currently coding an app that has a login and sign-up page with Parse as the backend. I am able to get the username and all of that registered, but I need help with the code that notifies the user if one of the fields are blank. I want to display the UIAlertView of the error and prevent the view from switching in this case (it switches and then displays the notification that the fields were left blank). I know it's probably something simple. Just need a little help. Here is the code below.
-(IBAction)signUpUserPressed:(id)sender
{
PFUser *user = [PFUser user];
user.username = self.userRegisterTextField.text;
user.password = self.passwordRegisterTextField.text;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
[self performSegueWithIdentifier:#"FinishSignup" sender:self];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error" message:[error userInfo][#"error"] delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil] show];
}
}];
}
Help would be much appreciated on this. This is also similar to if you are logging out of an app and it asks you if you would like to logout- stopping the view from switching and displaying the notification.
Thanks!
Before calling signUpInBackgroundWithBlock: check if the fields are empty yourself.
PFUser *user = [PFUser user];
user.username = self.userRegisterTextField.text;
user.password = self.passwordRegisterTextField.text;
if (user.username.length > 0 && user.password.length > 0) {
//sign up only if username/password given
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
[self performSegueWithIdentifier:#"FinishSignup" sender:self];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error" message:[error userInfo][#"error"] delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil] show];
}
}];
}
}
else {
//show alert that username or password was left blank
}

Upload photo using new iOS Facebook SDK API (3.0)

How can I upload a photo to facebook from an iOS app using their new API/SDK? I've already tried and I'm not getting anywhere, just keep running in circles. Here is the code I currently have:
-(void)dataForFaceboo{
self.postParams =
[[NSMutableDictionary alloc] initWithObjectsAndKeys:
self.uploadPhoto.image, #"picture", nil];
}
-(void)uploadToFacebook{
[self dataForFacebook];
NSLog(#"Going to facebook: %#", self.postParams);
// Hide keyboard if showing when button clicked
if ([self.photoCaption isFirstResponder]) {
[self.photoCaption resignFirstResponder];
}
// Add user message parameter if user filled it in
if (![self.photoCaption.text
isEqualToString:kPlaceholderPostMessage] &&
![self.photoCaption.text isEqualToString:#""])
{
[self.postParams setObject:self.photoCaption.text forKey:#"message"];
}
[FBRequestConnection startWithGraphPath:#"me/feed"
parameters:self.postParams
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat:
#"Posted action, id: %#",
[result objectForKey:#"id"]];
}
// Show the result in an alert
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:self
cancelButtonTitle:#"OK!"
otherButtonTitles:nil] show];
}];
}
Your code is fine, some slight changes to be done:
add the image to the dictionary in NSData format, like
[params setObject:UIImagePNGRepresentation(_image) forKey:#"picture"];
and change the graph path to "me/photos" instead of "me/feed"
Make these changes, it worked for me.
Remember you need to use "publish_actions" permissions.
"me/photos" is meant for the photo actually be in the "Photo's" list on your Facebook profile. "me/feed" is just a post on the timeline.