- Add Social Login
- Fix Vari
This commit is contained in:
parent
22499a85d3
commit
b0bcfad332
@ -135,13 +135,19 @@
|
|||||||
|
|
||||||
//if ([user isAuthenticated]) {
|
//if ([user isAuthenticated]) {
|
||||||
|
|
||||||
[User loginCurrentUserWithEmail:@"demo@packman.example" password:@"demo@packman.example" withBlockSuccess:^(PNUser * _Nullable responseObject) {
|
/*[User loginCurrentUserWithEmail:@"demo@packman.example" password:@"demo@packman.example" withBlockSuccess:^(PNUser * _Nullable responseObject) {
|
||||||
|
|
||||||
NSLog(@"response : %@",responseObject);
|
NSLog(@"response : %@",responseObject);
|
||||||
|
|
||||||
NSLog(@"%@",[User currentUser]);
|
NSLog(@"%@",[User currentUser]);
|
||||||
} failure:^(NSError * _Nonnull error) {
|
} failure:^(NSError * _Nonnull error) {
|
||||||
NSLog(@"response : %@",error);
|
NSLog(@"response : %@",error);
|
||||||
|
}];*/
|
||||||
|
|
||||||
|
[User socialLoginWithBlockSuccess:^(PNUser * _Nullable responseObject) {
|
||||||
|
|
||||||
|
} failure:^(NSError * _Nonnull error) {
|
||||||
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ PODS:
|
|||||||
- CocoaSecurity (~> 1.2.2)
|
- CocoaSecurity (~> 1.2.2)
|
||||||
- nv-ios-http-status (0.0.1)
|
- nv-ios-http-status (0.0.1)
|
||||||
- PEAR-FileManager-iOS (1.3.1)
|
- PEAR-FileManager-iOS (1.3.1)
|
||||||
- PNObject (0.4.6):
|
- PNObject (0.4.7):
|
||||||
- AFNetworking
|
- AFNetworking
|
||||||
- CodFis-Helper
|
- CodFis-Helper
|
||||||
- FBSDKCoreKit
|
- FBSDKCoreKit
|
||||||
@ -103,7 +103,7 @@ SPEC CHECKSUMS:
|
|||||||
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
|
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
|
||||||
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
||||||
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
||||||
PNObject: 20b785cb5cbf88322f2c268a5ba80ca3337dec51
|
PNObject: f2f42fe93c94b576eefca9c328d01a48212319d1
|
||||||
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
||||||
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
||||||
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
|
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
|
||||||
|
|||||||
1
Example/Pods/Headers/Private/PNObject/PNObjectUtilities.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PNObject/PNObjectUtilities.h
generated
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../Pod/Classes/PNObjectUtilities.h
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "PNObject",
|
"name": "PNObject",
|
||||||
"version": "0.4.6",
|
"version": "0.4.7",
|
||||||
"summary": "PNObject is a simple replica of the more complex ParseObject",
|
"summary": "PNObject is a simple replica of the more complex ParseObject",
|
||||||
"homepage": "https://github.com/giuseppenucifora/PNObject",
|
"homepage": "https://github.com/giuseppenucifora/PNObject",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"git": "https://github.com/giuseppenucifora/PNObject.git",
|
"git": "https://github.com/giuseppenucifora/PNObject.git",
|
||||||
"tag": "0.4.6"
|
"tag": "0.4.7"
|
||||||
},
|
},
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"ios": "8.0"
|
"ios": "8.0"
|
||||||
|
|||||||
4
Example/Pods/Manifest.lock
generated
4
Example/Pods/Manifest.lock
generated
@ -44,7 +44,7 @@ PODS:
|
|||||||
- CocoaSecurity (~> 1.2.2)
|
- CocoaSecurity (~> 1.2.2)
|
||||||
- nv-ios-http-status (0.0.1)
|
- nv-ios-http-status (0.0.1)
|
||||||
- PEAR-FileManager-iOS (1.3.1)
|
- PEAR-FileManager-iOS (1.3.1)
|
||||||
- PNObject (0.4.6):
|
- PNObject (0.4.7):
|
||||||
- AFNetworking
|
- AFNetworking
|
||||||
- CodFis-Helper
|
- CodFis-Helper
|
||||||
- FBSDKCoreKit
|
- FBSDKCoreKit
|
||||||
@ -103,7 +103,7 @@ SPEC CHECKSUMS:
|
|||||||
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
|
NSUserDefaults-AESEncryptor: da02cfef056f1e18ebe2748767915f08b274c9c5
|
||||||
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
nv-ios-http-status: b6c2b5fc8656cc19e0d3000dadce2080b99d0e2f
|
||||||
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
PEAR-FileManager-iOS: 3bc403f68a53483f5629aa822f4649e40275c4d3
|
||||||
PNObject: 20b785cb5cbf88322f2c268a5ba80ca3337dec51
|
PNObject: f2f42fe93c94b576eefca9c328d01a48212319d1
|
||||||
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
PureLayout: f35f5384c9c4e4479df041dbe33ad7577b71ddfb
|
||||||
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2
|
||||||
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
|
StrongestPasswordValidator: 921e42615bdf353513c6f925bffd4fc29865dbd7
|
||||||
|
|||||||
1276
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
1276
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
|||||||
buildForArchiving = "YES">
|
buildForArchiving = "YES">
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = 'primary'
|
BuildableIdentifier = 'primary'
|
||||||
BlueprintIdentifier = '24B6537E15CF8A8F679D4558'
|
BlueprintIdentifier = '97690789A9825EB1AAD67920'
|
||||||
BlueprintName = 'PNObject'
|
BlueprintName = 'PNObject'
|
||||||
ReferencedContainer = 'container:Pods.xcodeproj'
|
ReferencedContainer = 'container:Pods.xcodeproj'
|
||||||
BuildableName = 'PNObject.framework'>
|
BuildableName = 'PNObject.framework'>
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.4.6</string>
|
<string>0.4.7</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#import "PNObjectConstants.h"
|
#import "PNObjectConstants.h"
|
||||||
#import "PNObjectFormData.h"
|
#import "PNObjectFormData.h"
|
||||||
#import "PNObjectModel.h"
|
#import "PNObjectModel.h"
|
||||||
|
#import "PNObjectUtilities.h"
|
||||||
#import "AFJSONResponseSerializerWithData.h"
|
#import "AFJSONResponseSerializerWithData.h"
|
||||||
#import "AFHTTPRequestSerializer+OAuth2.h"
|
#import "AFHTTPRequestSerializer+OAuth2.h"
|
||||||
#import "AFOAuth2Manager.h"
|
#import "AFOAuth2Manager.h"
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "PNObject"
|
s.name = "PNObject"
|
||||||
s.version = "0.4.6"
|
s.version = "0.4.7"
|
||||||
s.summary = "PNObject is a simple replica of the more complex ParseObject"
|
s.summary = "PNObject is a simple replica of the more complex ParseObject"
|
||||||
|
|
||||||
# This description is used to generate tags and improve search results.
|
# This description is used to generate tags and improve search results.
|
||||||
|
|||||||
@ -76,9 +76,13 @@
|
|||||||
* @param success <#success description#>
|
* @param success <#success description#>
|
||||||
* @param failure <#failure description#>
|
* @param failure <#failure description#>
|
||||||
*/
|
*/
|
||||||
- (void) socialLoginWithBlockSuccessFromViewController:(UIViewController* _Nonnull) viewController
|
+ (void) socialLoginFromViewController:(UIViewController* _Nullable) viewController
|
||||||
blockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
blockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
||||||
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
||||||
|
|
||||||
|
|
||||||
|
+ (void) socialLoginWithBlockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
||||||
|
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <#Description#>
|
* <#Description#>
|
||||||
|
|||||||
@ -176,94 +176,92 @@ static bool isFirstAccess = YES;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (void) socialLoginWithBlockSuccessFromViewController:(UIViewController* _Nonnull) viewController
|
+ (void) socialLoginFromViewController:(UIViewController* _Nullable) viewController
|
||||||
blockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
blockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
||||||
failure:(nullable void (^)(NSError * _Nonnull error))failure {
|
failure:(nullable void (^)(NSError * _Nonnull error))failure {
|
||||||
|
|
||||||
|
if (!viewController) {
|
||||||
|
viewController = [PNObjectUtilities topViewController];
|
||||||
|
}
|
||||||
|
|
||||||
if ([FBSDKAccessToken currentAccessToken]) {
|
if ([FBSDKAccessToken currentAccessToken]) {
|
||||||
//FBSDKProfile *user = [FBSDKProfile currentProfile];
|
//FBSDKProfile *user = [FBSDKProfile currentProfile];
|
||||||
|
|
||||||
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"first_name, last_name, link, birthday, email, gender"}];
|
[FBSDKAccessToken refreshCurrentAccessToken:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||||
|
|
||||||
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
|
||||||
NSLogDebug(@"%@",result);
|
|
||||||
NSLogDebug(@"%@",error);
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
failure(error);
|
failure(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[self setFacebookAccessToken:[FBSDKAccessToken currentAccessToken].tokenString];
|
|
||||||
[self setFirstName:[result objectForKey:@"first_name"]];
|
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"first_name, last_name, link, birthday, email, gender"}];
|
||||||
[self setLastName:[result objectForKey:@"last_name"]];
|
|
||||||
[self setEmail:[result objectForKey:@"email"]];
|
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
|
||||||
[self setFacebookId:[result objectForKey:@"id"]];
|
NSLogDebug(@"%@",result);
|
||||||
|
NSLogDebug(@"%@",error);
|
||||||
NSString *gender = [[result objectForKey:@"gender"] isEqualToString:@"male"] ? @"M" : @"F";
|
|
||||||
|
if (error) {
|
||||||
[self setSex:gender];
|
if (failure) {
|
||||||
|
failure(error);
|
||||||
NSArray *birthArray = [[result objectForKey:@"birthday" ] componentsSeparatedByString: @"/"];
|
}
|
||||||
|
}
|
||||||
//NSMutableString *birthString = [NSMutableString stringWithString:[[[[[birthArray objectAtIndex:1] stringByAppendingString:@"/"] stringByAppendingString:[birthArray objectAtIndex:0]] stringByAppendingString:@"/"] stringByAppendingString:[birthArray objectAtIndex:2]]];
|
else {
|
||||||
|
[[PNObjectConfig sharedInstance] refreshTokenForUserWithFacebookID:[result objectForKey:@"id"] facebookToken:[FBSDKAccessToken currentAccessToken].tokenString withBlockSuccess:^(BOOL refreshSuccess) {
|
||||||
|
|
||||||
|
PNUser *user = [[self class] new];
|
||||||
|
|
||||||
|
[user setFacebookId:[result objectForKey:@"id"]];
|
||||||
|
[user setAuthenticated:YES];
|
||||||
|
[user saveLocally];
|
||||||
|
[user reloadFormServer];
|
||||||
|
|
||||||
|
USER = user;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
success(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
} failure:^(NSError * _Nonnull error) {
|
||||||
|
if (failure) {
|
||||||
|
failure(error);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[UserDataManager setParameter:DEF_PROFILE_FIRSTNAME withValue:user.firstName];
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_LASTNAME withValue:user.lastName];
|
|
||||||
|
|
||||||
NSArray *birthArray = [[result objectForKey:@"birthday" ] componentsSeparatedByString: @"/"];
|
|
||||||
|
|
||||||
NSMutableString *birthString = [NSMutableString stringWithString:[[[[[birthArray objectAtIndex:1] stringByAppendingString:@"/"] stringByAppendingString:[birthArray objectAtIndex:0]] stringByAppendingString:@"/"] stringByAppendingString:[birthArray objectAtIndex:2]]];
|
|
||||||
|
|
||||||
NSString *gender = [[result objectForKey:@"gender"] isEqualToString:@"male"] ? @"M" : @"F";
|
|
||||||
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_BIRTH withValue:birthString];
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_GENDER withValue:gender];
|
|
||||||
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_EMAIL withValue:[result objectForKey:@"email"]];
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_AVATAR withValue:[NSNumber numberWithInt:1]];
|
|
||||||
[UserDataManager setParameter:DEF_PROFILE_FB_ID withValue:[result objectForKey:@"id"]];*/
|
|
||||||
|
|
||||||
|
|
||||||
//[self setFacebookId:[user userID]];
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
|
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
|
||||||
[login logInWithReadPermissions: @[@"public_profile",@"email"] fromViewController:viewController handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
|
[login logInWithReadPermissions: @[@"public_profile",@"email",@"user_birthday"] fromViewController:viewController handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
NSLog(@"Process error");
|
NSLog(@"Process error");
|
||||||
|
if (failure) {
|
||||||
|
failure(error);
|
||||||
|
}
|
||||||
} else if (result.isCancelled) {
|
} else if (result.isCancelled) {
|
||||||
NSLog(@"Cancelled");
|
NSLog(@"Cancelled");
|
||||||
|
if (failure) {
|
||||||
|
NSError *error = [NSError errorWithDomain:NSLocalizedString(@"Request cancelled", @"") code:kHTTPStatusCodeMethodNotAllowed userInfo:nil];
|
||||||
|
failure(error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
NSLog(@"Logged in");
|
NSLog(@"Logged in");
|
||||||
|
[self socialLoginFromViewController:viewController blockSuccess:success failure:failure];
|
||||||
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) socialLoginWithBlockSuccess:(void (^)(PNUser * _Nullable))success
|
;
|
||||||
failure:(void (^)(NSError * _Nonnull))failure {
|
|
||||||
|
|
||||||
|
|
||||||
/*[self POSTWithEndpointAction:@"registration/register" progress:nil success:^(NSURLSessionDataTask * _Nullable task, PNObject * _Nullable responseObject) {
|
+ (void) socialLoginWithBlockSuccess:(nullable void (^)(PNUser * _Nullable responseObject))success
|
||||||
NSLog(@"response %@",responseObject);
|
failure:(nullable void (^)(NSError * _Nonnull error))failure {
|
||||||
if(success){
|
|
||||||
success(self);
|
[self socialLoginFromViewController:nil blockSuccess:success failure:failure];
|
||||||
[self saveLocally];
|
|
||||||
}
|
|
||||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
|
||||||
NSLogDebug(@"error : %ld",[error code]);
|
|
||||||
if (failure) {
|
|
||||||
failure(error);
|
|
||||||
}
|
|
||||||
}];*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void) loginCurrentUserWithEmail:(NSString * _Nonnull) email
|
+ (void) loginCurrentUserWithEmail:(NSString * _Nonnull) email
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "PNObjectConfig.h"
|
#import "PNObjectConfig.h"
|
||||||
#import "PNObjectModel.h"
|
#import "PNObjectModel.h"
|
||||||
|
#import "PNObjectUtilities.h"
|
||||||
|
|
||||||
#pragma mark MappingSelector Keys
|
#pragma mark MappingSelector Keys
|
||||||
|
|
||||||
|
|||||||
@ -183,6 +183,12 @@ extern NSString* _Nonnull const Client_Secret;
|
|||||||
password:(NSString * _Nonnull) password
|
password:(NSString * _Nonnull) password
|
||||||
withBlockSuccess:(nullable void (^)(BOOL refreshSuccess))success
|
withBlockSuccess:(nullable void (^)(BOOL refreshSuccess))success
|
||||||
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
||||||
|
|
||||||
|
|
||||||
|
- (void) refreshTokenForUserWithFacebookID:(NSString * _Nonnull) facebookID
|
||||||
|
facebookToken:(NSString * _Nonnull) facebookToken
|
||||||
|
withBlockSuccess:(nullable void (^)(BOOL refreshSuccess))success
|
||||||
|
failure:(nullable void (^)(NSError * _Nonnull error))failure;
|
||||||
/**
|
/**
|
||||||
* <#Description#>
|
* <#Description#>
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
#import "NSUserDefaults+AESEncryptor.h"
|
#import "NSUserDefaults+AESEncryptor.h"
|
||||||
#import "NASecRandom.h"
|
#import "NASecRandom.h"
|
||||||
#import "NAKeychain.h"
|
#import "NAKeychain.h"
|
||||||
|
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||||
|
|
||||||
NSString * const PNObjectLocalNotificationRefreshTokenClientCredentialSuccess = @"PNObjectLocalNotificationRefreshTokenClientCredentialSuccess";
|
NSString * const PNObjectLocalNotificationRefreshTokenClientCredentialSuccess = @"PNObjectLocalNotificationRefreshTokenClientCredentialSuccess";
|
||||||
NSString * const PNObjectLocalNotificationRefreshTokenClientCredentialFail = @"PNObjectLocalNotificationRefreshTokenClientCredentialFail";
|
NSString * const PNObjectLocalNotificationRefreshTokenClientCredentialFail = @"PNObjectLocalNotificationRefreshTokenClientCredentialFail";
|
||||||
@ -347,6 +348,9 @@ static bool isFirstAccess = YES;
|
|||||||
[self refreshTokenForUserWithEmail:[[SINGLETON.userSubClass currentUser] email] password:[[(PNUser*)[SINGLETON.userSubClass currentUser] password] password] withBlockSuccess:success failure:failure];
|
[self refreshTokenForUserWithEmail:[[SINGLETON.userSubClass currentUser] email] password:[[(PNUser*)[SINGLETON.userSubClass currentUser] password] password] withBlockSuccess:success failure:failure];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if ([SINGLETON.userSubClass currentUser] && [[SINGLETON.userSubClass currentUser] facebookId]){
|
||||||
|
[self refreshTokenForUserWithFacebookID:[[SINGLETON.userSubClass currentUser] facebookId] facebookToken:[[FBSDKAccessToken currentAccessToken] tokenString] withBlockSuccess:success failure:failure];
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
|
|
||||||
@ -399,6 +403,46 @@ static bool isFirstAccess = YES;
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) refreshTokenForUserWithFacebookID:(NSString * _Nonnull) facebookID
|
||||||
|
facebookToken:(NSString * _Nonnull) facebookToken
|
||||||
|
withBlockSuccess:(nullable void (^)(BOOL refreshSuccess))success
|
||||||
|
failure:(nullable void (^)(NSError * _Nonnull error))failure {
|
||||||
|
if (!facebookID || [facebookID length] == 0) {
|
||||||
|
if (failure) {
|
||||||
|
NSError *error = [NSError errorWithDomain:NSLocalizedString(@"Facebook id is not valid", @"") code:kHTTPStatusCodeBadRequest userInfo:nil];
|
||||||
|
failure(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!facebookToken || [facebookToken length] == 0) {
|
||||||
|
if (failure) {
|
||||||
|
NSError *error = [NSError errorWithDomain:NSLocalizedString(@"Facebook token is not valid", @"") code:kHTTPStatusCodeBadRequest userInfo:nil];
|
||||||
|
failure(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[_authManager authenticateUsingFacebookOAuthWithURLString:[_currentEndPointBaseUrl stringByAppendingString:@"oauth-token"] facebookID:facebookID facebookToken:facebookToken scope:nil success:^(AFOAuthCredential * _Nonnull credential) {
|
||||||
|
_currentOauthCredential = credential;
|
||||||
|
|
||||||
|
[AFOAuthCredential storeCredential:_currentOauthCredential withIdentifier:PNObjectServiceCredentialIdentifier];
|
||||||
|
|
||||||
|
[_httpSerializer setAuthorizationHeaderFieldWithCredential:_currentOauthCredential];
|
||||||
|
[_jsonSerializer setAuthorizationHeaderFieldWithCredential:_currentOauthCredential];
|
||||||
|
[_authManager.requestSerializer setAuthorizationHeaderFieldWithCredential:_currentOauthCredential];
|
||||||
|
[_manager.requestSerializer setAuthorizationHeaderFieldWithCredential:_currentOauthCredential];
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
success(YES);
|
||||||
|
}
|
||||||
|
} failure:^(NSError * _Nonnull error) {
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:PNObjectLocalNotificationRefreshTokenUserFail object:error];
|
||||||
|
if (failure) {
|
||||||
|
failure(error);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) refreshTokenForClientCredential {
|
- (void) refreshTokenForClientCredential {
|
||||||
[self refreshTokenForClientCredentialWithBlockSuccess:nil failure:nil];
|
[self refreshTokenForClientCredentialWithBlockSuccess:nil failure:nil];
|
||||||
}
|
}
|
||||||
|
|||||||
15
Pod/Classes/PNObjectUtilities.h
Normal file
15
Pod/Classes/PNObjectUtilities.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// PNObjectUtilities.h
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Giuseppe Nucifora on 17/03/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface PNObjectUtilities : NSObject
|
||||||
|
|
||||||
|
+ (UIViewController *) topViewController;
|
||||||
|
|
||||||
|
@end
|
||||||
33
Pod/Classes/PNObjectUtilities.m
Normal file
33
Pod/Classes/PNObjectUtilities.m
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// PNObjectUtilities.m
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Giuseppe Nucifora on 17/03/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PNObjectUtilities.h"
|
||||||
|
|
||||||
|
@implementation PNObjectUtilities
|
||||||
|
|
||||||
|
+ (UIViewController *)topViewController {
|
||||||
|
return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIViewController *)topViewController:(UIViewController *)rootViewController
|
||||||
|
{
|
||||||
|
if (rootViewController.presentedViewController == nil) {
|
||||||
|
return rootViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([rootViewController.presentedViewController isKindOfClass:[UINavigationController class]]) {
|
||||||
|
UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
|
||||||
|
UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
|
||||||
|
return [self topViewController:lastViewController];
|
||||||
|
}
|
||||||
|
|
||||||
|
UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
|
||||||
|
return [self topViewController:presentedViewController];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -109,6 +109,23 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
success:(void (^)(AFOAuthCredential *credential))success
|
success:(void (^)(AFOAuthCredential *credential))success
|
||||||
failure:(void (^)(NSError *error))failure;
|
failure:(void (^)(NSError *error))failure;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates and enqueues an `NSURLSessionTask` to authenticate against the server using a specified facebook id and facebook token, with a designated scope.
|
||||||
|
|
||||||
|
@param URLString The URL string used to create the request URL.
|
||||||
|
@param facebookID The facebook id used for authentication
|
||||||
|
@param facebookToken The facebook token used for authentication
|
||||||
|
@param scope The authorization scope
|
||||||
|
@param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes a single argument: the OAuth credential returned by the server.
|
||||||
|
@param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error returned from the server.
|
||||||
|
*/
|
||||||
|
- (NSURLSessionTask *)authenticateUsingFacebookOAuthWithURLString:(NSString *)URLString
|
||||||
|
facebookID:(NSString *)facebookid
|
||||||
|
facebookToken:(NSString *)facebookToken
|
||||||
|
scope:(NSString *)scope
|
||||||
|
success:(void (^)(AFOAuthCredential * _Nonnull))success
|
||||||
|
failure:(void (^)(NSError * _Nonnull))failure;
|
||||||
/**
|
/**
|
||||||
Creates and enqueues an `NSURLSessionTask` to authenticate against the server with a designated scope.
|
Creates and enqueues an `NSURLSessionTask` to authenticate against the server with a designated scope.
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ NSString * const kAFOAuthClientCredentialsGrantType = @"client_credentials";
|
|||||||
NSString * const kAFOAuthPasswordCredentialsGrantType = @"password";
|
NSString * const kAFOAuthPasswordCredentialsGrantType = @"password";
|
||||||
NSString * const kAFOAuthCodeGrantType = @"authorization_code";
|
NSString * const kAFOAuthCodeGrantType = @"authorization_code";
|
||||||
NSString * const kAFOAuthRefreshGrantType = @"refresh_token";
|
NSString * const kAFOAuthRefreshGrantType = @"refresh_token";
|
||||||
|
NSString * const kAFOAuthFacebookCredentialGrantType = @"provider_facebook_token";
|
||||||
|
|
||||||
NSString * const AFOAuth2ErrorDomain = @"com.alamofire.networking.oauth2.error";
|
NSString * const AFOAuth2ErrorDomain = @"com.alamofire.networking.oauth2.error";
|
||||||
|
|
||||||
@ -35,9 +36,9 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
if (![object valueForKey:@"error"] || [[object valueForKey:@"error"] isEqual:[NSNull null]]) {
|
if (![object valueForKey:@"error"] || [[object valueForKey:@"error"] isEqual:[NSNull null]]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableDictionary *mutableUserInfo = [NSMutableDictionary dictionary];
|
NSMutableDictionary *mutableUserInfo = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
NSString *description = nil;
|
NSString *description = nil;
|
||||||
if ([object valueForKey:@"error_description"]) {
|
if ([object valueForKey:@"error_description"]) {
|
||||||
description = [object valueForKey:@"error_description"];
|
description = [object valueForKey:@"error_description"];
|
||||||
@ -54,15 +55,15 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
description = NSLocalizedStringFromTable(@"The authorization grant type is not supported by the authorization server.", @"AFOAuth2Manager", @"invalid_request");
|
description = NSLocalizedStringFromTable(@"The authorization grant type is not supported by the authorization server.", @"AFOAuth2Manager", @"invalid_request");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (description) {
|
if (description) {
|
||||||
mutableUserInfo[NSLocalizedDescriptionKey] = description;
|
mutableUserInfo[NSLocalizedDescriptionKey] = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([object valueForKey:@"error_uri"]) {
|
if ([object valueForKey:@"error_uri"]) {
|
||||||
mutableUserInfo[NSLocalizedRecoverySuggestionErrorKey] = [object valueForKey:@"error_uri"];
|
mutableUserInfo[NSLocalizedRecoverySuggestionErrorKey] = [object valueForKey:@"error_uri"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [NSError errorWithDomain:AFOAuth2ErrorDomain code:-1 userInfo:mutableUserInfo];
|
return [NSError errorWithDomain:AFOAuth2ErrorDomain code:-1 userInfo:mutableUserInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,19 +102,19 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
NSParameterAssert(url);
|
NSParameterAssert(url);
|
||||||
NSParameterAssert(clientID);
|
NSParameterAssert(clientID);
|
||||||
NSParameterAssert(secret);
|
NSParameterAssert(secret);
|
||||||
|
|
||||||
self = [super initWithBaseURL:url sessionConfiguration:configuration];
|
self = [super initWithBaseURL:url sessionConfiguration:configuration];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.serviceProviderIdentifier = [self.baseURL host];
|
self.serviceProviderIdentifier = [self.baseURL host];
|
||||||
self.clientID = clientID;
|
self.clientID = clientID;
|
||||||
self.secret = secret;
|
self.secret = secret;
|
||||||
self.useHTTPBasicAuthentication = YES;
|
self.useHTTPBasicAuthentication = YES;
|
||||||
|
|
||||||
[self.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
|
[self.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
|
|
||||||
- (void)setUseHTTPBasicAuthentication:(BOOL)useHTTPBasicAuthentication {
|
- (void)setUseHTTPBasicAuthentication:(BOOL)useHTTPBasicAuthentication {
|
||||||
_useHTTPBasicAuthentication = useHTTPBasicAuthentication;
|
_useHTTPBasicAuthentication = useHTTPBasicAuthentication;
|
||||||
|
|
||||||
if (self.useHTTPBasicAuthentication) {
|
if (self.useHTTPBasicAuthentication) {
|
||||||
[self.requestSerializer setAuthorizationHeaderFieldWithUsername:self.clientID password:self.secret];
|
[self.requestSerializer setAuthorizationHeaderFieldWithUsername:self.clientID password:self.secret];
|
||||||
} else {
|
} else {
|
||||||
@ -133,11 +134,11 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
if (!secret) {
|
if (!secret) {
|
||||||
secret = @"";
|
secret = @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
_secret = secret;
|
_secret = secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
- (NSURLSessionTask *)authenticateUsingOAuthWithURLString:(NSString *)URLString
|
- (NSURLSessionTask *)authenticateUsingOAuthWithURLString:(NSString *)URLString
|
||||||
username:(NSString *)username
|
username:(NSString *)username
|
||||||
@ -147,31 +148,53 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
failure:(void (^)(NSError * _Nonnull))failure {
|
failure:(void (^)(NSError * _Nonnull))failure {
|
||||||
NSParameterAssert(username);
|
NSParameterAssert(username);
|
||||||
NSParameterAssert(password);
|
NSParameterAssert(password);
|
||||||
|
|
||||||
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||||
[parameters setValue:kAFOAuthPasswordCredentialsGrantType forKey:@"grant_type"];
|
[parameters setValue:kAFOAuthPasswordCredentialsGrantType forKey:@"grant_type"];
|
||||||
[parameters setValue:username forKey:@"username"];
|
[parameters setValue:username forKey:@"username"];
|
||||||
[parameters setValue:password forKey:@"password"];
|
[parameters setValue:password forKey:@"password"];
|
||||||
|
|
||||||
if (scope) {
|
if (scope) {
|
||||||
[parameters setValue:scope forKey:@"scope"];
|
[parameters setValue:scope forKey:@"scope"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSURLSessionTask *)authenticateUsingFacebookOAuthWithURLString:(NSString *)URLString
|
||||||
|
facebookID:(NSString *)facebookid
|
||||||
|
facebookToken:(NSString *)facebookToken
|
||||||
|
scope:(NSString *)scope
|
||||||
|
success:(void (^)(AFOAuthCredential * _Nonnull))success
|
||||||
|
failure:(void (^)(NSError * _Nonnull))failure {
|
||||||
|
NSParameterAssert(facebookid);
|
||||||
|
NSParameterAssert(facebookToken);
|
||||||
|
|
||||||
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||||
|
[parameters setValue:kAFOAuthFacebookCredentialGrantType forKey:@"grant_type"];
|
||||||
|
[parameters setValue:facebookid forKey:@"username"];
|
||||||
|
[parameters setValue:facebookToken forKey:@"password"];
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
[parameters setValue:scope forKey:@"scope"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
- (NSURLSessionTask *)authenticateUsingOAuthWithURLString:(NSString *)URLString
|
- (NSURLSessionTask *)authenticateUsingOAuthWithURLString:(NSString *)URLString
|
||||||
scope:(NSString *)scope
|
scope:(NSString *)scope
|
||||||
success:(void (^)(AFOAuthCredential * _Nonnull))success
|
success:(void (^)(AFOAuthCredential * _Nonnull))success
|
||||||
failure:(void (^)(NSError * _Nonnull))failure {
|
failure:(void (^)(NSError * _Nonnull))failure {
|
||||||
|
|
||||||
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||||
[parameters setValue:kAFOAuthClientCredentialsGrantType forKey:@"grant_type"];
|
[parameters setValue:kAFOAuthClientCredentialsGrantType forKey:@"grant_type"];
|
||||||
|
|
||||||
if (scope) {
|
if (scope) {
|
||||||
[parameters setValue:scope forKey:@"scope"];
|
[parameters setValue:scope forKey:@"scope"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,12 +205,12 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
failure:(void (^)(NSError *error))failure
|
failure:(void (^)(NSError *error))failure
|
||||||
{
|
{
|
||||||
NSParameterAssert(refreshToken);
|
NSParameterAssert(refreshToken);
|
||||||
|
|
||||||
NSDictionary *parameters = @{
|
NSDictionary *parameters = @{
|
||||||
@"grant_type": kAFOAuthRefreshGrantType,
|
@"grant_type": kAFOAuthRefreshGrantType,
|
||||||
@"refresh_token": refreshToken
|
@"refresh_token": refreshToken
|
||||||
};
|
};
|
||||||
|
|
||||||
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,13 +222,13 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
{
|
{
|
||||||
NSParameterAssert(code);
|
NSParameterAssert(code);
|
||||||
NSParameterAssert(uri);
|
NSParameterAssert(uri);
|
||||||
|
|
||||||
NSDictionary *parameters = @{
|
NSDictionary *parameters = @{
|
||||||
@"grant_type": kAFOAuthCodeGrantType,
|
@"grant_type": kAFOAuthCodeGrantType,
|
||||||
@"code": code,
|
@"code": code,
|
||||||
@"redirect_uri": uri
|
@"redirect_uri": uri
|
||||||
};
|
};
|
||||||
|
|
||||||
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +243,7 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
mutableParameters[@"client_secret"] = self.secret;
|
mutableParameters[@"client_secret"] = self.secret;
|
||||||
}
|
}
|
||||||
parameters = [NSDictionary dictionaryWithDictionary:mutableParameters];
|
parameters = [NSDictionary dictionaryWithDictionary:mutableParameters];
|
||||||
|
|
||||||
NSURLSessionTask *task;
|
NSURLSessionTask *task;
|
||||||
task = [self POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
task = [self POST:URLString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
|
||||||
if (!responseObject) {
|
if (!responseObject) {
|
||||||
@ -229,46 +252,46 @@ static NSError * AFErrorFromRFC6749Section5_2Error(id object) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([responseObject valueForKey:@"error"]) {
|
if ([responseObject valueForKey:@"error"]) {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
failure(AFErrorFromRFC6749Section5_2Error(responseObject));
|
failure(AFErrorFromRFC6749Section5_2Error(responseObject));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *refreshToken = [responseObject valueForKey:@"refresh_token"];
|
NSString *refreshToken = [responseObject valueForKey:@"refresh_token"];
|
||||||
if (!refreshToken || [refreshToken isEqual:[NSNull null]]) {
|
if (!refreshToken || [refreshToken isEqual:[NSNull null]]) {
|
||||||
refreshToken = [parameters valueForKey:@"refresh_token"];
|
refreshToken = [parameters valueForKey:@"refresh_token"];
|
||||||
}
|
}
|
||||||
|
|
||||||
AFOAuthCredential *credential = [AFOAuthCredential credentialWithOAuthToken:[responseObject valueForKey:@"access_token"] tokenType:[responseObject valueForKey:@"token_type"]];
|
AFOAuthCredential *credential = [AFOAuthCredential credentialWithOAuthToken:[responseObject valueForKey:@"access_token"] tokenType:[responseObject valueForKey:@"token_type"]];
|
||||||
|
|
||||||
|
|
||||||
if (refreshToken) { // refreshToken is optional in the OAuth2 spec
|
if (refreshToken) { // refreshToken is optional in the OAuth2 spec
|
||||||
[credential setRefreshToken:refreshToken];
|
[credential setRefreshToken:refreshToken];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expiration is optional, but recommended in the OAuth2 spec. It not provide, assume distantFuture === never expires
|
// Expiration is optional, but recommended in the OAuth2 spec. It not provide, assume distantFuture === never expires
|
||||||
NSDate *expireDate = [NSDate distantFuture];
|
NSDate *expireDate = [NSDate distantFuture];
|
||||||
id expiresIn = [responseObject valueForKey:@"expires_in"];
|
id expiresIn = [responseObject valueForKey:@"expires_in"];
|
||||||
if (expiresIn && ![expiresIn isEqual:[NSNull null]]) {
|
if (expiresIn && ![expiresIn isEqual:[NSNull null]]) {
|
||||||
expireDate = [NSDate dateWithTimeIntervalSinceNow:[expiresIn doubleValue]];
|
expireDate = [NSDate dateWithTimeIntervalSinceNow:[expiresIn doubleValue]];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expireDate) {
|
if (expireDate) {
|
||||||
[credential setExpiration:expireDate];
|
[credential setExpiration:expireDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
success(credential);
|
success(credential);
|
||||||
}
|
}
|
||||||
|
|
||||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
failure(error);
|
failure(error);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user