Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to integrate 'Sign in with Apple' flow in iOS Objective-C?

I want to integrate 'Sign in with Apple' in my iOS app. I have found many code examples for this but all are in Swift and I need Objective-C.

like image 792
Yogendra Patel Avatar asked Nov 12 '19 07:11

Yogendra Patel


People also ask

Is Objective-C still used for iOS?

Objective-C is so pervasive in iOS that it's impossible to completely remove it. Apple continues to maintain libraries written in Objective-C, so we should expect Objective-C to be treated as a (mostly) first class language in iOS. At other companies, legacy code remains.

Is Apple stopping supporting Objective-C?

This end of support will take place in July 31, 2021. Customers currently using the legacy Objective-C SDK should transition to the Swift version of the SDK. The iOS Swift Workspace ONE SDK will be the only native language SDK offered for iOS going forward.

Can you make an iOS app with Objective-C?

iOS applications are typically developed in a programming language called Objective-C and supported by a support library called Cocoa Touch.


1 Answers

Step -1 :

for reference purpose I taken the information from here iOS 13 — Sign In with Apple Tutorial and here

for full code you can download from github-Sign-In-with-Apple

Adding Sign In With Apple Capability

Under the Xcode project file, there is Signing & Capabilities available. Press on the + and add the “Sign In with Apple” capability.

enter image description here

Step -2

add the AuthenticationServices framework in target --> general --> frameworks and #import<AuthenticationServices/AuthenticationServices.h> in your viewcontroller

enter image description here

Step-3

in here I created the setCurrentIdentifier object for save the current user and I created the textview for show the Output in the screen.

assign the delegate <ASAuthorizationControllerDelegate,ASAuthorizationControllerPresentationContextProviding> in your interface

extern NSString* const setCurrentIdentifier;

@interface ViewController : UIViewController<ASAuthorizationControllerDelegate,ASAuthorizationControllerPresentationContextProviding>

@property (nonatomic, strong) UITextView *appleIDLoginInfoTextView;
NSString* const setCurrentIdentifier = @"setCurrentIdentifier";

Step-4

on your controller UI loads setup your object and observeAppleSignInState like below

 @synthesize appleIDLoginInfoTextView;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    if (@available(iOS 13.0, *)) {
           [self observeAppleSignInState];
           [self setupUI];
       }

}

- (void)observeAppleSignInState {
    if (@available(iOS 13.0, *)) {
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(handleSignInWithAppleStateChanged:) name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
    }
}

- (void)handleSignInWithAppleStateChanged:(id)noti {    
    NSLog(@"%s", __FUNCTION__);
    NSLog(@"%@", noti);
}


- (void)setupUI {

    // Sign In With Apple 
    appleIDLoginInfoTextView = [[UITextView alloc] initWithFrame:CGRectMake(.0, 40.0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) * 0.4) textContainer:nil];
    appleIDLoginInfoTextView.font = [UIFont systemFontOfSize:32.0];
    [self.view addSubview:appleIDLoginInfoTextView];


    if (@available(iOS 13.0, *)) {
    // Sign In With Apple Button
    ASAuthorizationAppleIDButton *appleIDButton = [ASAuthorizationAppleIDButton new];

    appleIDButton.frame =  CGRectMake(.0, .0, CGRectGetWidth(self.view.frame) - 40.0, 100.0);
    CGPoint origin = CGPointMake(20.0, CGRectGetMidY(self.view.frame));
    CGRect frame = appleIDButton.frame;
    frame.origin = origin;
    appleIDButton.frame = frame;
    appleIDButton.cornerRadius = CGRectGetHeight(appleIDButton.frame) * 0.25;
    [self.view addSubview:appleIDButton];
    [appleIDButton addTarget:self action:@selector(handleAuthrization:) forControlEvents:UIControlEventTouchUpInside];
    }

    NSMutableString *mStr = [NSMutableString string];
    [mStr appendString:@"Sign In With Apple \n"];
    appleIDLoginInfoTextView.text = [mStr copy];
}


- (void)handleAuthrization:(UIButton *)sender {
    if (@available(iOS 13.0, *)) {
        // A mechanism for generating requests to authenticate users based on their Apple ID.
        ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];

        // Creates a new Apple ID authorization request.
        ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
        // The contact information to be requested from the user during authentication.
        request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];

        // A controller that manages authorization requests created by a provider.
        ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];

        // A delegate that the authorization controller informs about the success or failure of an authorization attempt.
        controller.delegate = self;

        // A delegate that provides a display context in which the system can present an authorization interface to the user.
        controller.presentationContextProvider = self;

        // starts the authorization flows named during controller initialization.
        [controller performRequests];
    }
}

Step - 4

handle your delegates

 - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization  API_AVAILABLE(ios(13.0)){

    NSLog(@"%s", __FUNCTION__);
    NSLog(@"%@", controller);
    NSLog(@"%@", authorization);

    NSLog(@"authorization.credential:%@", authorization.credential);

    NSMutableString *mStr = [NSMutableString string];
    mStr = [appleIDLoginInfoTextView.text mutableCopy];

    if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
        // ASAuthorizationAppleIDCredential
        ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
        NSString *user = appleIDCredential.user;
        [[NSUserDefaults standardUserDefaults] setValue:user forKey:setCurrentIdentifier];
        [mStr appendString:user?:@""];
        NSString *familyName = appleIDCredential.fullName.familyName;
        [mStr appendString:familyName?:@""];
        NSString *givenName = appleIDCredential.fullName.givenName;
        [mStr appendString:givenName?:@""];
        NSString *email = appleIDCredential.email;
        [mStr appendString:email?:@""];
        NSLog(@"mStr:%@", mStr);
        [mStr appendString:@"\n"];
        appleIDLoginInfoTextView.text = mStr;

    } else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
        ASPasswordCredential *passwordCredential = authorization.credential;
        NSString *user = passwordCredential.user;
        NSString *password = passwordCredential.password;
        [mStr appendString:user?:@""];
        [mStr appendString:password?:@""];
        [mStr appendString:@"\n"];
        NSLog(@"mStr:%@", mStr);
        appleIDLoginInfoTextView.text = mStr;
    } else {
         mStr = [@"check" mutableCopy];
        appleIDLoginInfoTextView.text = mStr;
    }
}


- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error  API_AVAILABLE(ios(13.0)){

    NSLog(@"%s", __FUNCTION__);
    NSLog(@"error :%@", error);
    NSString *errorMsg = nil;
    switch (error.code) {
        case ASAuthorizationErrorCanceled:
            errorMsg = @"ASAuthorizationErrorCanceled";
            break;
        case ASAuthorizationErrorFailed:
            errorMsg = @"ASAuthorizationErrorFailed";
            break;
        case ASAuthorizationErrorInvalidResponse:
            errorMsg = @"ASAuthorizationErrorInvalidResponse";
            break;
        case ASAuthorizationErrorNotHandled:
            errorMsg = @"ASAuthorizationErrorNotHandled";
            break;
        case ASAuthorizationErrorUnknown:
            errorMsg = @"ASAuthorizationErrorUnknown";
            break;
    }

    NSMutableString *mStr = [appleIDLoginInfoTextView.text mutableCopy];
    [mStr appendString:errorMsg];
    [mStr appendString:@"\n"];
    appleIDLoginInfoTextView.text = [mStr copy];

    if (errorMsg) {
        return;
    }

    if (error.localizedDescription) {
        NSMutableString *mStr = [appleIDLoginInfoTextView.text mutableCopy];
        [mStr appendString:error.localizedDescription];
        [mStr appendString:@"\n"];
        appleIDLoginInfoTextView.text = [mStr copy];
    }
    NSLog(@"controller requests:%@", controller.authorizationRequests);
    /*
     ((ASAuthorizationAppleIDRequest *)(controller.authorizationRequests[0])).requestedScopes
     <__NSArrayI 0x2821e2520>(
     full_name,
     email
     )
     */
}

//! Tells the delegate from which window it should present content to the user.
 - (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller  API_AVAILABLE(ios(13.0)){

    NSLog(@"window:%s", __FUNCTION__);
    return self.view.window;
}

- (void)dealloc {

    if (@available(iOS 13.0, *)) {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
    }
}

job done , if you run the code you get the output as below

enter image description here

like image 96
Anbu.Karthik Avatar answered Nov 06 '22 04:11

Anbu.Karthik