Skip to content

Instantly share code, notes, and snippets.

@benjiwheeler
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benjiwheeler/efd315158e14ad4e4173 to your computer and use it in GitHub Desktop.
Save benjiwheeler/efd315158e14ad4e4173 to your computer and use it in GitHub Desktop.
Parse User Subclass for use with FB
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <Parse/PFObject+Subclass.h>
@interface MyParseUser : PFUser <PFSubclassing>
+ (MyParseUser *)currentUser;
+ (void)doFbLoginWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler;
+ (BOOL)ensureLinkedToFB;
+ (BOOL)isLinkedToFB;
- (NSString*)fbValueForKey:(NSString*)key;
+ (void)ensureHasFBInfoWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler;
+ (void)fetchFacebookDataWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler;
- (void)gotFacebookDataWithResult:(NSDictionary *)resultParam;
- (UIImage *)profileImg;
+ (NSString *)imgUrlForFacebookId:(NSString *)facebookId;
+ (NSString *)largeImgUrlForFacebookId:(NSString *)facebookId;
- (void)setParseUserForInstallation;
@end
#import "MyParseUser.h"
#import <FacebookSDK/FacebookSDK.h>
@implementation MyParseUser
-(id)init
{
self = [super init];//WithClassName:@"MyParseUser"];
if (self) {
}
return self;
}
// user pressed button to login with fb
+ (void)doFbLoginWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler {
NSArray *permissionsArray = @[ @"user_about_me", @"user_birthday", @"user_location", @"email"];
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
// stop animating loading indicator here if we're doing that
if (!user) {
if (!error) {
DLog(@"Uh oh. The user cancelled the Facebook login.");
handler(NO, @"Need to come up with an error here to show that they cancelled the login");
} else {
DLog(@"Uh oh. An error occurred: %@", error);
handler(NO, error);
// NOTE: this is an error
}
} else if (user.isNew) {
DLog(@"User with facebook signed up and logged in!");
// Send request for the details to Facebook
[MyParseUser fetchFacebookDataWithCompletion:^(BOOL success, id responseOrError) {
if (success) {
DLog(@"doFbLoginWithCompletion ok, has fb info");
handler(YES, user);
} else {
DLog(@"doFbLoginWithCompletion failed to fetch fb info");
// NOTE: this is an error
handler(NO, responseOrError);
}
}];
} else { // user previously authed us
DLog(@"User with facebook logged in!");
// unclear what we should do here. most of the time no need to Send request to Facebook because we already have the info we need. but sometimes this is a new install on a new device.
[MyParseUser fetchFacebookDataWithCompletion:^(BOOL success, id responseOrError) {
if (success) {
DLog(@"doFbLoginWithCompletion ok, has fb info");
handler(YES, user);
} else {
DLog(@"doFbLoginWithCompletion failed to fetch fb info");
// NOTE: this is an error
handler(NO, responseOrError);
}
}];
}
}];
}
+ (BOOL)ensureLinkedToFB
{
// Check if user is cached and linked to Facebook, if not, logout
if ([MyParseUser isLinkedToFB]) {
return YES;
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"LogoutUser" object:nil];
return NO;
}
}
+ (BOOL)isLinkedToFB
{
if ([MyParseUser currentUser] && [PFFacebookUtils isLinkedWithUser:[MyParseUser currentUser]]) {
return YES;
} else {
return NO;
}
}
+ (MyParseUser *)currentUser {
return (MyParseUser *)[PFUser currentUser];
}
+ (void)ensureHasFBInfoWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler
{
if ([MyParseUser ensureLinkedToFB]) {
if ([[MyParseUser currentUser] fbValueForKey:@"facebookId"] != nil) { // Check if it has fb info
handler(YES, nil);
} else { // linked but doesn't have data yet
[MyParseUser fetchFacebookDataWithCompletion:^(BOOL success, id responseOrError) {
if (success) {
DLog(@"MyParseUser::ensureHasFBInfoWithCompletion successfully fetched fb data");
[[MyParseUser currentUser] setParseUserForInstallation]; // usually overkill
handler(YES, nil);
} else {
DLog(@"MyParseUser::ensureHasFBInfoWithCompletion failed to fetch fb data");
handler(NO, nil);
}
}];
}
} // if not linked, will go to logout
}
+ (void)fetchFacebookDataWithCompletion:(void ( ^ )(BOOL success, id responseOrError))handler
{
if ([MyParseUser ensureLinkedToFB]) {
FBRequest *request = [FBRequest requestForMe];
// Send request to Facebook
[request startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
[[MyParseUser currentUser] gotFacebookDataWithResult:(NSDictionary*)result];
handler(YES, nil);
} else if ([error.userInfo[FBErrorParsedJSONResponseKey][@"body"][@"error"][@"MyPe"] isEqualToString:@"OAuthException"]) { // Since the request failed, we can check if it was due to an invalid session
DLog(@"The facebook session was invalidated");
} else {
DLog(@"Some other error: %@", error);
}
}];
}
}
- (void)gotFacebookDataWithResult:(NSDictionary *)resultParam
{
NSString *facebookId = resultParam[@"id"];
NSMutableDictionary *userProfile = [NSMutableDictionary dictionaryWithCapacity:8];
if (facebookId) userProfile[@"facebookId"] = facebookId;
if (resultParam[@"name"]) userProfile[@"name"] = resultParam[@"name"];
if (resultParam[@"email"]) userProfile[@"email"] = resultParam[@"email"];
if (resultParam[@"location"][@"name"]) userProfile[@"location"] = resultParam[@"location"][@"name"];
if (resultParam[@"gender"]) userProfile[@"gender"] = resultParam[@"gender"];
if (resultParam[@"birthday"]) userProfile[@"birthday"] = resultParam[@"birthday"];
if (facebookId != nil) userProfile[@"pictureURL"] = [MyParseUser imgUrlForFacebookId:facebookId];
[self setObject:userProfile forKey:@"fbprofile"];
[self saveInBackground];
}
- (UIImage *)profileImg
{
NSData * imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[MyParseUser imgUrlForFacebookId:[self fbValueForKey:@"facebookId"]]]];
UIImage *fbProfileImg = [UIImage imageWithData: imageData];
return fbProfileImg;
}
+ (NSString *)imgUrlForFacebookId:(NSString *)facebookId
{
NSString *pictureURL = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?MyPe=small&return_ssl_resources=1", facebookId];
return pictureURL;
}
+ (NSString *)largeImgUrlForFacebookId:(NSString *)facebookId
{
NSString *pictureURL = [NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?MyPe=large&return_ssl_resources=1", facebookId];
return pictureURL;
}
- (NSString *)fbValueForKey:(NSString*)key
{
if ([self objectForKey:@"fbprofile"]) {
return [[self objectForKey:@"fbprofile"] objectForKey:key];
} else {
return nil;
}
}
- (void)setParseUserForInstallation
{
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setObject:self forKey:@"user"];
[currentInstallation saveEventually];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment