閑話少說(shuō)藕施,直接上碼
一. 開啟Sign in with Apple 功能
1. app bundle id 開啟Sign in with Apple
登陸developer賬號(hào),在app bundle ID的Capabilities里督暂,打勾Sign In with Apple
.
打勾Sign in with Apple
2. Xcode里開啟Sign in with Apple
打開Xcode 11.0 Beta或更新版本辜限,在項(xiàng)目設(shè)置 -> Signing & Capabilities 里皇拣,開啟Sign in with Apple
選項(xiàng)。
在Xcode中開啟Sign in with Apple
二. 實(shí)現(xiàn)
實(shí)現(xiàn)概括
實(shí)現(xiàn)分四大部分:
- 創(chuàng)建
Sign in with Apple
Button. - 跟用戶提出授權(quán)請(qǐng)求.
- 根據(jù)用戶的授權(quán)來(lái)驗(yàn)證用戶.
- 處理用戶授權(quán)變更.
1. 創(chuàng)建Sign in with Apple
Button
import UIKit
import AuthenticationServices
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = ASAuthorizationAppleIDButton()
button.addTarget(self, action: #selector(handleAuthorization), for: .touchUpInside)
// `handleAuthorization`的實(shí)現(xiàn)參閱:2. 跟用戶提出授權(quán)請(qǐng)求.
// 創(chuàng)建好button后薄嫡,可以安裝需求安裝到所需的位置氧急, 比如 self.view.addSubview(button)
}
}
2. 跟用戶提出授權(quán)請(qǐng)求.
-
handleAuthorization
里主要是跟用戶提出用蘋果登陸請(qǐng)求,并要求用戶提供用戶名和email. - 發(fā)出請(qǐng)求需要?jiǎng)?chuàng)建
ASAuthorizationController
, 但是需要提供delegate
和presentationContextProvider
.-
ASAuthorizationControllerDelegate
會(huì)提供請(qǐng)求后的結(jié)果回調(diào)毫深,比如用戶請(qǐng)求失敗吩坝,或者用戶請(qǐng)求成功。 -
presentationContextProvider
是為驗(yàn)證的用戶界面提供所需的window
.
-
@objc private func handleAuthorization() {
if #available(iOS 13.0, *) {
let requestID = ASAuthorizationAppleIDProvider().createRequest()
// 這里請(qǐng)求了用戶的姓名和email
requestID.requestedScopes = [.fullName, .email]
let controller = ASAuthorizationController(authorizationRequests: [requestID])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
} else {
// iOS13以前的版本不支持哑蔫, 用戶界面可以提示
}
}
@available(iOS 13.0, *)
extension ViewController: ASAuthorizationControllerDelegate
{
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
// 請(qǐng)求完成钉寝,但是有錯(cuò)誤
}
func authorizationController(controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization)
{
// 請(qǐng)求完成, 用戶通過(guò)驗(yàn)證
if let credential = authorization.credential as? ASAuthorizationAppleIDCredential
{
// 拿到用戶的驗(yàn)證信息闸迷,這里可以跟自己服務(wù)器所存儲(chǔ)的信息進(jìn)行校驗(yàn)嵌纲,比如用戶名是否存在等。
let detailVC = DetailVC(cred: credential)
self.present(detailVC, animated: true, completion: nil)
}
}
}
@available(iOS 13.0, *)
extension ViewController: ASAuthorizationControllerPresentationContextProviding
{
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return (UIApplication.shared.delegate as! AppDelegate).window!
}
}
3. 根據(jù)用戶的授權(quán)來(lái)驗(yàn)證用戶.
if let credential = authorization.credential as? ASAuthorizationAppleIDCredential
在上面ASAuthorizationControllerDelegate
的用戶通過(guò)驗(yàn)證的回調(diào)里腥沽,可以拿到credential
逮走,這里面有一些信息值得提下:
- 用戶emai:
credential.email
- 用戶名信息:
credential.fullName
- 蘋果提供的用戶ID:
credential.user
- 驗(yàn)證信息狀態(tài):
credential.state
- refresh token:
let code = credential.authorizationCode, let codeStr = String(data: code, encoding: .utf8)
- access token:
let idToken = credential.identityToken, let tokeStr = String(data: idToken, encoding: .utf8)
4. 處理用戶授權(quán)/用戶信息變更.
授權(quán)或者用戶信息是有可能被改變的,我們能做到就是盡早的檢測(cè)出這樣的改變巡球,并做以應(yīng)對(duì)言沐。
檢測(cè)授權(quán)的狀態(tài)需要記錄在上面所得到的
“蘋果提供的用戶ID:
credential.user
”
在AppleDelegate
里,把之前存的用戶ID放到ASAuthorizationAppleIDProvider
里驗(yàn)證即可酣栈,可以得到幾種用戶授權(quán)狀態(tài):
-
authorized
: 授權(quán)合格/合法 -
revoked
:授權(quán)被撤銷险胰,用戶可以在iOS系統(tǒng)設(shè)置了手動(dòng)撤銷授權(quán)。 -
notFound
:授權(quán)未找到
class AppDelegate: UIResponder, UIApplicationDelegate
{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let userID = Keychain.getSavedUserID() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: "") { (state, error) in
switch state
{
case .authorized: // 處理合法的授權(quán)
break
case .revoked: // 處理被撤銷的授權(quán)
break
case .notFound: //處理沒(méi)有找到的授權(quán)
break
default: // 其他
break
}
}
}
return true
}
}
如果有錯(cuò)誤歡迎指出矿筝,也歡迎各種討論起便,謝??!