Search code examples
iosobjective-cios13apple-sign-in

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.


Solution

  • 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