1顷歌、配置app套餐的Identifiers支持Sign In With Apple
如下圖
2宾尚、項(xiàng)目配置
3巩掺、集成代碼
主要步驟:
使用ASAuthorizationAppleIDButton創(chuàng)建button,布局蚤蔓,添加點(diǎn)擊事件搏讶;
實(shí)現(xiàn)點(diǎn)擊事件:授權(quán)請(qǐng)求
授權(quán)代理實(shí)現(xiàn)(授權(quán)成功,授權(quán)失敺园浮)ASAuthorizationControllerDelegate
驗(yàn)證
已經(jīng)Sign In with Apple登陸過(guò)app的用戶棚赔,處理
監(jiān)聽(tīng)授權(quán)狀態(tài)改變
4、實(shí)現(xiàn)
使用ASAuthorizationAppleIDButton創(chuàng)建button,布局徘郭,添加點(diǎn)擊事件靠益;
-(void)createView
{ ? ?
? ? ? if(@available(iOS13.0,*))
? ? ? ? ?{ASAuthorizationAppleIDButton*appleIDButton=[[ASAuthorizationAppleIDButton alloc]init];
? ? ? ? ?appleIDButton.frame=CGRectMake(50,100+CGRectGetHeight(self.view.frame)*0.4,CGRectGetWidth(self.view.frame)-100,50);
? ? ? ? ?[appleIDButton addTarget:selfaction:@selector(appleIDButtonClicked)forControlEvents:UIControlEventTouchUpInside];
? ? ? ? [self.view addSubview:appleIDButton];
? ? ? }
}
實(shí)現(xiàn)點(diǎn)擊事件:授權(quán)請(qǐng)求
-(void)appleIDButtonClickedAPI_AVAILABLE(ios(13.0)){
//基于用戶的Apple ID授權(quán)用戶,生成用戶授權(quán)請(qǐng)求的一種機(jī)制
ASAuthorizationAppleIDProvider*provide=[[ASAuthorizationAppleIDProvideralloc]init];
//創(chuàng)建新的AppleID 授權(quán)請(qǐng)求
ASAuthorizationAppleIDRequest*request=provide.createRequest;
//在用戶授權(quán)期間請(qǐng)求的聯(lián)系信息
request.requestedScopes=@[ASAuthorizationScopeFullName,ASAuthorizationScopeEmail];
//由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請(qǐng)求 管理授權(quán)請(qǐng)求的控制器
ASAuthorizationController*controller=[[ASAuthorizationControlleralloc]initWithAuthorizationRequests:@[request]];
//設(shè)置授權(quán)控制器通知授權(quán)請(qǐng)求的成功與失敗的代理
controller.delegate=self;
//設(shè)置提供 展示上下文的代理残揉,在這個(gè)上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
controller.presentationContextProvider=self;
//在控制器初始化期間啟動(dòng)授權(quán)流
[controller performRequests];
}
授權(quán)代理實(shí)現(xiàn)(授權(quán)成功胧后,授權(quán)失敗)ASAuthorizationControllerDelegate驗(yàn)證
#pragmamark - ASAuthorizationControllerDelegate
//授權(quán)成功的回調(diào)
/**
當(dāng)授權(quán)成功后抱环,我們可以通過(guò)這個(gè)拿到用戶的 userID壳快、email、fullName镇草、authorizationCode眶痰、identityToken 以及 realUserStatus 等信息。
*/
-(void)authorizationController:(ASAuthorizationController*)controller didCompleteWithAuthorization:(ASAuthorization*)authorizationAPI_AVAILABLE(ios(13.0)){
? ? ? ? ?if([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]){
? ? ? ? ? ? ? ? // 用戶登錄使用ASAuthorizationAppleIDCredential
? ? ? ? ? ? ? ? ASAuthorizationAppleIDCredential*credential=authorization.credential;
? ? ? ? ? ? ? ? //蘋(píng)果用戶唯一標(biāo)識(shí)符梯啤,該值在同一個(gè)開(kāi)發(fā)者賬號(hào)下的所有 App 下是一樣的竖伯,開(kāi)發(fā)者可以用該唯一標(biāo)識(shí)符與自己后臺(tái)系統(tǒng)的賬號(hào)體系綁定起來(lái)。
? ? ? ? ? ? ? ? NSString*userId=credential.user;
? ? ? ? ? ? ? ? ?NSString*state=credential.state;
? ? ? ? ? ? ? ? ?NSPersonNameComponents*fullName=credential.fullName;
? ? ? ? ? ? ? ? ?//蘋(píng)果用戶信息条辟,郵箱
? ? ? ? ? ? ? ? ?NSString*email=credential.email;
? ? ? ? ? ? ? ? ?NSString*authorizationCode=[[NSString alloc]initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding];// refresh token
? ? ? ? /**
? ? ? ? 驗(yàn)證數(shù)據(jù)黔夭,用于傳給開(kāi)發(fā)者后臺(tái)服務(wù)器宏胯,然后開(kāi)發(fā)者服務(wù)器再向蘋(píng)果的身份驗(yàn)證服務(wù)端驗(yàn)證本次授權(quán)登錄請(qǐng)求數(shù)據(jù)的有效性和真實(shí)性羽嫡,詳見(jiàn) Sign In with Apple REST API。如果驗(yàn)證成功肩袍,可以根據(jù) userIdentifier 判斷賬號(hào)是否已存在杭棵,若存在,則返回自己賬號(hào)系統(tǒng)的登錄態(tài),若不存在魂爪,則創(chuàng)建一個(gè)新的賬號(hào)先舷,并返回對(duì)應(yīng)的登錄態(tài)給 App。
? ? ? ? */
? ? ? ? ? ? ? ? ? ? ?NSString*identityToken=[[NSString alloc]initWithData:credential.identityToken encoding:NSUTF8StringEncoding];/**
? ? ? ? ? ? ? ? ? ? ? 用于判斷當(dāng)前登錄的蘋(píng)果賬號(hào)是否是一個(gè)真實(shí)用戶
? ? ? ? ? ? ? ? ? ? ? ?取值有:unsupported滓侍、unknown蒋川、likelyReal。
? ? ? ? */
ASUserDetectionStatus realUserStatus=credential.realUserStatus;
// 存儲(chǔ)userId到keychain中撩笆,代碼省略······
}elseif([authorization.credential isKindOfClass:[ASPasswordCredential class]]){
// 用戶登錄使用現(xiàn)有的密碼憑證
ASPasswordCredential*passwordCredential=authorization.credential;
// 密碼憑證對(duì)象的用戶標(biāo)識(shí) 用戶的唯一標(biāo)識(shí)
NSString*user=passwordCredential.user;
// 密碼憑證對(duì)象的密碼
NSString*password=passwordCredential.password;
_appleIDInfoTextView.text=[NSString stringWithFormat:@"%@",passwordCredential];
}else{
}
}
//失敗的回調(diào)
-(void)authorizationController:(ASAuthorizationController*)controller didCompleteWithError:(NSError*)errorAPI_AVAILABLE(ios(13.0)){
}
#pragmamark - ASAuthorizationControllerPresentationContextProviding
//告訴代理應(yīng)該在哪個(gè)window 展示授權(quán)界面給用戶
-(ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController*)controllerAPI_AVAILABLE(ios(13.0)){
return ? self.view.window;
}
已經(jīng)Sign In with Apple登陸過(guò)app的用戶
1捺球、如果設(shè)備中存在iCloud Keychain憑證或者AppleID憑證,提示用戶直接使用TouchID或FaceID登錄即可夕冲。
2氮兵、新增ASAuthorizationPasswordRequest,如果 KeyChain 里面有登錄信息的話歹鱼,可以直接使用里面保存的用戶名和密碼進(jìn)行登錄泣栈。
-(void)perfomExistingAccountSetupFlows{
if(@available(iOS13.0,*)){
// 授權(quán)請(qǐng)求依賴于用于的AppleID
ASAuthorizationAppleIDRequest*authAppleIDRequest=[[ASAuthorizationAppleIDProvidernew]createRequest];
// 為了執(zhí)行鑰匙串憑證分享生成請(qǐng)求的一種機(jī)制
ASAuthorizationPasswordRequest*passwordRequest=[[ASAuthorizationPasswordProvidernew]createRequest];
NSMutableArray<ASAuthorizationRequest*>*mArr=[NSMutableArrayarrayWithCapacity:2];
if(authAppleIDRequest){
[mArr addObject:authAppleIDRequest];
}
if(passwordRequest){
[mArr addObject:passwordRequest];
}
// ASAuthorizationRequest:對(duì)于不同種類授權(quán)請(qǐng)求的基類
NSArray<ASAuthorizationRequest*>*requests=[mArr copy];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請(qǐng)求 管理授權(quán)請(qǐng)求的控制器
ASAuthorizationController*authorizationController=[[ASAuthorizationControlleralloc]initWithAuthorizationRequests:requests];
// 設(shè)置授權(quán)控制器通知授權(quán)請(qǐng)求的成功與失敗的代理
authorizationController.delegate=self;
// 設(shè)置提供 展示上下文的代理,在這個(gè)上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
authorizationController.presentationContextProvider=self;
// 在控制器初始化期間啟動(dòng)授權(quán)流
[authorizationController performRequests];
? ? }
}
在 App 使用過(guò)程中弥姻,通過(guò)通知方法來(lái)監(jiān)聽(tīng) revoked 狀態(tài)
-(void)observeAppleSignInState{
if(@available(iOS13.0,*)){
NSNotificationCenter*center=[NSNotificationCenter defaultCenter];
[center addObserver:selfselector:@selector(handleSignInWithAppleStateChanged:)name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
}
}
// 觀察SignInWithApple狀態(tài)改變
-(void)handleSignInWithAppleStateChanged:(id)noti{
}
程序啟動(dòng)時(shí)南片,監(jiān)聽(tīng)授權(quán)狀態(tài)
用戶終止 App 中使用 Sign in with Apple 功能;
用戶在設(shè)置里注銷了 AppleId時(shí)
App 需要獲取到這些狀態(tài)庭敦,然后做退出登錄操作铃绒,或者重新登錄。
我們需要在 App 啟動(dòng)的時(shí)候螺捐,通過(guò) getCredentialState:completion: 來(lái)獲取當(dāng)前用戶的授權(quán)狀態(tài)颠悬。
-(void)observeAuthticationState
{
// 基于用戶的Apple ID 生成授權(quán)用戶請(qǐng)求的機(jī)制
ASAuthorizationAppleIDProvider*appleIDProvider=[ASAuthorizationAppleIDProvider new];
// 注意 存儲(chǔ)用戶標(biāo)識(shí)信息需要使用鑰匙串來(lái)存儲(chǔ) 這里使用NSUserDefaults 做的簡(jiǎn)單示例
NSString*userIdentifier=[[NSUserDefaults standardUserDefaults]valueForKey:@"ShareCurrentIdentifier"];
if(userIdentifier){
// 在回調(diào)中返回用戶的授權(quán)狀態(tài)
[appleIDProvider getCredentialStateForUserID:userIdentifier completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState,NSError*_Nullable error){
// 蘋(píng)果證書(shū)的授權(quán)狀態(tài)
switch(credentialState)
{
case ?ASAuthorizationAppleIDProviderCredentialRevoked:
// 蘋(píng)果授權(quán)憑證失效
dispatch_async(dispatch_get_main_queue(),^{
//做對(duì)應(yīng)處理
});
break;
case ? ? ASAuthorizationAppleIDProviderCredentialAuthorized:
// 蘋(píng)果授權(quán)憑證狀態(tài)良好
dispatch_async(dispatch_get_main_queue(),^{
//做對(duì)應(yīng)處理
});
break;
case ? ASAuthorizationAppleIDProviderCredentialNotFound:
// 未發(fā)現(xiàn)蘋(píng)果授權(quán)憑證
// 可以引導(dǎo)用戶重新登錄
dispatch_async(dispatch_get_main_queue(),^{
//做對(duì)應(yīng)處理
});
break;
default:
break;
}
}];
}
}
官網(wǎng)swift版demo和改編的OC版 ? ?https://github.com/wanggang1128/WGSignInWithApple
http://www.reibang.com/p/921ea520e8b3