Last active
August 29, 2015 14:02
-
-
Save benjiwheeler/efd315158e14ad4e4173 to your computer and use it in GitHub Desktop.
Parse User Subclass for use with FB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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