版本記錄
版本號 | 時(shí)間 |
---|---|
V1.0 | 2019.10.17 星期四 |
前言
今天翻閱蘋果的API文檔直晨,發(fā)現(xiàn)多了一個(gè)框架SwiftUI搀军,這里我們就一起來看一下這個(gè)框架。感興趣的看下面幾篇文章勇皇。
1. SwiftUI框架詳細(xì)解析 (一) —— 基本概覽(一)
2. SwiftUI框架詳細(xì)解析 (二) —— 基于SwiftUI的閃屏頁的創(chuàng)建(一)
3. SwiftUI框架詳細(xì)解析 (三) —— 基于SwiftUI的閃屏頁的創(chuàng)建(二)
開始
主要內(nèi)容:了解如何使用SwiftUI實(shí)施與Apple的登錄罩句,以為用戶提供更多的隱私和對iOS應(yīng)用程序的控制,本篇翻譯來自地址敛摘。
下面看下寫作環(huán)境
Swift 5, iOS 13, Xcode 11
使用Apple登錄(Sign In with Apple)
是iOS 13
中的一項(xiàng)新功能门烂,可以更快地在您的應(yīng)用程序中注冊和認(rèn)證。
盡管Apple反復(fù)聲明“與Apple登錄”易于實(shí)現(xiàn)兄淫,但仍存在一些需要管理的地方屯远。 在本教程中,您不僅將學(xué)習(xí)如何正確使用Apple實(shí)施登錄捕虽,而且還將學(xué)習(xí)如何使用SwiftUI慨丐!
您需要Xcode 11
,付費(fèi)的Apple Developer
會(huì)員身份和iOS 13設(shè)備泄私,才能隨本教程一起學(xué)習(xí)房揭。
注意:您需要一臺(tái)運(yùn)行iOS 13的實(shí)際設(shè)備。模擬器并不總是能夠正常運(yùn)行晌端。
由于您將在設(shè)備上運(yùn)行并處理授權(quán)捅暴,因此請轉(zhuǎn)到“項(xiàng)目”導(dǎo)航器,然后單擊新的Signing & Capabilities
標(biāo)簽咧纠,以設(shè)置團(tuán)隊(duì)標(biāo)識符并適當(dāng)更新包標(biāo)識符伶唯。 如果您現(xiàn)在構(gòu)建并運(yùn)行該應(yīng)用程序,則會(huì)看到正常的登錄屏幕:
注意:您可以忽略Xcode顯示的兩個(gè)警告惧盹。 您將在教程中對其進(jìn)行修復(fù)乳幸。
Add Capabilities
您的配置(PP)
文件需要具有Sign In with Apple
功能瞪讼,因此請立即添加。 在項(xiàng)目導(dǎo)航器中單擊項(xiàng)目粹断,選擇SignInWithApple
目標(biāo)符欠,然后單擊Signing & Capabilities
選項(xiàng)卡。 最后瓶埋,單擊+ Capability
希柿,然后添加使用Apple登錄功能。
如果您的應(yīng)用程序具有關(guān)聯(lián)的網(wǎng)站养筒,則還應(yīng)該添加Associated Domains
功能曾撤。 此步驟是完全可選的,對于本教程或使用Apple登錄功能來說不是必需的晕粪。 如果確實(shí)選擇使用關(guān)聯(lián)的域挤悉,請確保將“域” Domains
值設(shè)置為字符串webcredentials :
,后跟域名巫湘。 例如装悲,您可以使用webcredentials:www.mydomain.com
。 在本教程的后面尚氛,您將了解需要對網(wǎng)站進(jìn)行的更改诀诊。
Add Sign In Button
Apple沒有為Sign In with Apple
按鈕提供SwiftUI
視圖,因此您需要自己包裝阅嘶。 創(chuàng)建一個(gè)名為SignInWithApple.swift
的新文件属瓣,然后粘貼此代碼。
import SwiftUI
import AuthenticationServices
// 1
final class SignInWithApple: UIViewRepresentable {
// 2
func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
// 3
return ASAuthorizationAppleIDButton()
}
// 4
func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {
}
}
這是正在做的事情:
- 1) 需要包裝
UIView
時(shí)讯柔,可以將UIViewRepresentable
子類化奠涌。 - 2)
makeUIView
應(yīng)該始終返回特定類型的UIView
。 - 3) 由于您沒有執(zhí)行任何自定義操作磷杏,因此直接返回“使用Apple登錄”對象溜畅。
- 4) 由于視圖的狀態(tài)永遠(yuǎn)不變,因此請保留一個(gè)空的實(shí)現(xiàn)极祸。
現(xiàn)在您可以將按鈕添加到SwiftUI
慈格,打開ContentView.swift
并將其添加到UserAndPassword
視圖的正下方:
SignInWithApple()
.frame(width: 280, height: 60)
Apple
的樣式指南要求最小尺寸為280×60
,因此請務(wù)必遵循遥金。 構(gòu)建并運(yùn)行您的應(yīng)用程序浴捆,您應(yīng)該會(huì)看到按鈕!
Handle Button Taps
現(xiàn)在稿械,點(diǎn)擊按鈕不會(huì)執(zhí)行任何操作选泻。 在設(shè)置按鈕frame
的位置下方,添加一個(gè)手勢識別:
.onTapGesture(perform: showAppleLogin)
然后在body
屬性之后實(shí)現(xiàn)showAppleLogin()
:
private func showAppleLogin() {
// 1
let request = ASAuthorizationAppleIDProvider().createRequest()
// 2
request.requestedScopes = [.fullName, .email]
// 3
let controller = ASAuthorizationController(authorizationRequests: [request])
}
這是您設(shè)置的內(nèi)容:
- 1) 所有登錄請求都需要一個(gè)
ASAuthorizationAppleIDRequest
。 - 2) 指定您需要知道的最終用戶數(shù)據(jù)的類型页眯。
- 3) 生成將顯示登錄對話框的控制器梯捕。
您應(yīng)該僅請求所需的用戶數(shù)據(jù)。 Apple為您生成一個(gè)用戶ID窝撵。因此傀顾,如果獲取電子郵件的唯一目的是擁有一個(gè)唯一的標(biāo)識符,那么您就不需要它了碌奉,所以請不要請求短曾。
1. ASAuthorizationControllerDelegate
當(dāng)用戶嘗試進(jìn)行身份驗(yàn)證時(shí),Apple
將調(diào)用兩個(gè)委托方法之一赐劣,因此請立即實(shí)施嫉拐。打開SignInWithAppleDelegates.swift
。您將在此處實(shí)現(xiàn)代碼魁兼,該代碼將在用戶點(diǎn)擊按鈕后運(yùn)行婉徘。雖然您可以在自己的視圖中實(shí)現(xiàn)代碼,但將代碼放置在其他位置以提高可重用性會(huì)更簡潔璃赡。
您現(xiàn)在只需將authorizationController(controller:didCompleteWithError :)
保留為空判哥,但在生產(chǎn)應(yīng)用中献雅,應(yīng)處理這些錯(cuò)誤碉考。
授權(quán)成功后,將調(diào)用authorizationController(controller:didCompleteWithAuthorization :)
挺身。您可以在下載的示例代碼中看到兩種情況侯谁。通過檢查credential
屬性,可以確定用戶是通過Apple ID
還是通過存儲(chǔ)的iCloud
密碼進(jìn)行了身份驗(yàn)證章钾。
傳遞給委托方法的ASAuthorization
對象包括您要求的任何屬性墙贱,例如電子郵件或名稱。該值的存在是您如何確定這是新注冊還是現(xiàn)有登錄名的方式贱傀。
注意:Apple只會(huì)在首次身份驗(yàn)證時(shí)為您提供所需的詳細(xì)信息惨撇。
記住前面的注釋至關(guān)重要! Apple
假設(shè)您將存儲(chǔ)所需的詳細(xì)信息府寒,因此不再需要它們魁衙。這是您需要處理的“與Apple登錄”的地方之一。
考慮用戶首次登錄的情況株搔,因此您需要執(zhí)行注冊。 Apple向您提供用戶的電子郵件和全名。然后碰煌,您嘗試調(diào)用您的服務(wù)器注冊代碼堕扶。除非您的服務(wù)器不在線或設(shè)備的網(wǎng)絡(luò)連接斷開等役拴。
用戶下次登錄時(shí)姜性,Apple不會(huì)提供詳細(xì)信息儡炼,因?yàn)樗M呀?jīng)擁有這些詳細(xì)信息妹田。這將導(dǎo)致existing user
流運(yùn)行沮趣,從而導(dǎo)致失敗。
2. Handling Registration
在authorizationController(controller:didCompleteWithAuthorization :)
的第一個(gè)case
語句中露懒,添加以下內(nèi)容:
// 1
if let _ = appleIdCredential.email, let _ = appleIdCredential.fullName {
// 2
registerNewAccount(credential: appleIdCredential)
} else {
// 3
signInWithExistingAccount(credential: appleIdCredential)
}
在此代碼中:
- 1) 如果您收到詳細(xì)信息纺涤,則表明它是新注冊拧咳。
- 2) 收到詳細(xì)信息后汪厨,請調(diào)用您的注冊方法狭吼。
- 3) 如果您沒有收到詳細(xì)信息,請調(diào)用您現(xiàn)有的帳戶方法殖妇。
將以下注冊方法粘貼到擴(kuò)展名的頂部:
private func registerNewAccount(credential: ASAuthorizationAppleIDCredential) {
// 1
let userData = UserData(email: credential.email!,
name: credential.fullName!,
identifier: credential.user)
// 2
let keychain = UserDataKeychain()
do {
try keychain.store(userData)
} catch {
self.signInSucceeded(false)
}
// 3
do {
let success = try WebApi.Register(
user: userData,
identityToken: credential.identityToken,
authorizationCode: credential.authorizationCode
)
self.signInSucceeded(success)
} catch {
self.signInSucceeded(false)
}
}
這里做了一些事情:
- 1) 將所需的詳細(xì)信息和Apple提供的
user
保存在結(jié)構(gòu)體中。 - 2) 將詳細(xì)信息存儲(chǔ)到
iCloud
鑰匙串中以備后用葱椭。 - 3) 調(diào)用您的服務(wù),并向調(diào)用者表明注冊是否成功粪小。
請注意credential.user
的用法。此屬性包含Apple
分配給最終用戶的唯一標(biāo)識符。當(dāng)您將此用戶存儲(chǔ)在服務(wù)器上時(shí)逞壁,請使用此值(而不是電子郵件或登錄名)流济。提供的值將在用戶擁有的所有設(shè)備上完全匹配。此外腌闯,Apple將為與您的Team ID
相關(guān)聯(lián)的所有應(yīng)用程序?yàn)橛脩籼峁┫嗤闹瞪痢S脩暨\(yùn)行的任何應(yīng)用均會(huì)收到相同的ID
,這意味著您已經(jīng)在服務(wù)器上擁有了他們的所有信息姿骏,無需要求用戶提供它糖声!
您服務(wù)器的數(shù)據(jù)庫可能已經(jīng)為用戶存儲(chǔ)了其他標(biāo)識符。只需在您的user
類型表中添加一個(gè)新列分瘦,其中包含Apple提供的標(biāo)識符蘸泻。然后,您的服務(wù)器端代碼將首先檢查該列是否匹配嘲玫。如果未找到悦施,請還原為現(xiàn)有的登錄或注冊流程,例如使用電子郵件地址或登錄名去团。
根據(jù)服務(wù)器處理安全性的方式抡诞,您可能會(huì)或可能不需要發(fā)送credential.identityToken
和credential.authorizationCode
拜马。 OAuth
流使用這兩部分?jǐn)?shù)據(jù)。 OAuth
設(shè)置超出了本教程的范圍沐绒。
注意:Apple提供了使用
OAuth
詳細(xì)信息生成其公鑰所需的數(shù)據(jù)俩莽。本質(zhì)上,他們?yōu)槟峁┝?code>JSON Web Key (JWK)乔遮。
為了確保在鑰匙串中正確存儲(chǔ)扮超,請?jiān)?code>CredentialStorage中編輯UserDataKeychain.swift
并更新account
以獲取應(yīng)用程序的包標(biāo)識符,然后附加任何其他文本值蹋肮。我喜歡在包標(biāo)識符后附加.Details
出刷。重要的是,account
屬性和包標(biāo)識符不完全匹配坯辩,因此存儲(chǔ)的值僅用于您打算使用的目的馁龟。
3. Handling Existing Accounts
如前所述,現(xiàn)有用戶登錄到您的應(yīng)用程序時(shí)漆魔,Apple
不會(huì)提供電子郵件和全名坷檩。在SignInWithAppleDelegates.swift
中的注冊方法下面添加此方法以處理這種情況:
private func signInWithExistingAccount(credential: ASAuthorizationAppleIDCredential) {
// You *should* have a fully registered account here. If you get back an error
// from your server that the account doesn't exist, you can look in the keychain
// for the credentials and rerun setup
// if (WebAPI.login(credential.user,
// credential.identityToken,
// credential.authorizationCode)) {
// ...
// }
self.signInSucceeded(true)
}
您在此方法中放置的代碼將非常針對應(yīng)用程序。 如果您從服務(wù)器收到失敗消息改抡,告知您該用戶尚未注冊矢炼,則應(yīng)使用retrieve()
查詢鑰匙串。 使用返回的UserData
結(jié)構(gòu)的詳細(xì)信息阿纤,然后重新嘗試注冊最終用戶句灌。
4. Username and Password
與Apple一起使用登錄時(shí),另一種可能性是最終用戶將選擇已存儲(chǔ)在該站點(diǎn)的iCloud
鑰匙串中的憑據(jù)credentials
欠拾。 在authorizationController(controller:didCompleteWithAuthorization :)
的第二種case
語句中胰锌,添加以下行:
signInWithUserAndPassword(credential: passwordCredential)
然后在signInWithExistingAccount(credential :)
下面,實(shí)現(xiàn)適當(dāng)?shù)姆椒ǎ?/p>
private func signInWithUserAndPassword(credential: ASPasswordCredential) {
// if (WebAPI.login(credential.user, credential.password)) {
// ...
// }
self.signInSucceeded(true)
}
同樣藐窄,您的實(shí)現(xiàn)將針對特定應(yīng)用资昧。 但是,您需要調(diào)用服務(wù)器登錄名并傳遞用戶名和密碼枷邪。 如果服務(wù)器無法識別用戶榛搔,則您將需要運(yùn)行完整的注冊流程诺凡,因?yàn)槟痪邆滂€匙串中提供的有關(guān)其電子郵件和姓名的任何詳細(xì)信息东揣。
Finish Handling Button Press
返回ContentView.swift
,您需要一個(gè)屬性來存儲(chǔ)剛創(chuàng)建的代理腹泌。 在類的頂部嘶卧,添加以下代碼行:
@State var appleSignInDelegates: SignInWithAppleDelegates! = nil
@State
是告訴SwiftUI
的結(jié)構(gòu)將擁有其擁有并更新的可變內(nèi)容。 所有@State
屬性必須具有一個(gè)實(shí)際值凉袱,這就是為什么出現(xiàn)nil
奇怪的賦值的原因芥吟。
現(xiàn)在侦铜,在同一文件中,用以下命令替換controller
創(chuàng)建钟鸵,以完成showAppleLogin()
:
// 1
appleSignInDelegates = SignInWithAppleDelegates() { success in
if success {
// update UI
} else {
// show the user an error
}
}
// 2
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = appleSignInDelegates
// 3
controller.performRequests()
這是正在做的事情:
- 1) 生成代理并將其分配給類的屬性钉稍。
- 2) 像以前一樣生成
ASAuthorizationController
,但是這次棺耍,告訴它使用您的自定義委托類贡未。 - 3) 通過調(diào)用
performRequests()
,您要求iOS
顯示Sign In with Apple
模式視圖蒙袍。
代理的回調(diào)是根據(jù)最終用戶是否成功通過您的應(yīng)用進(jìn)行身份驗(yàn)證來處理任何必要的展示更改的地方俊卤。
Automate Sign In
您已經(jīng)實(shí)現(xiàn)了使用Apple登錄的功能,但是用戶必須明確點(diǎn)擊該按鈕害幅。 如果已將他們帶到登錄頁面消恍,則應(yīng)查看他們是否已配置Sign In with Apple
。 返回ContentView.swift
以现,將此行添加到.onAppear
塊中:
self.performExistingAccountSetupFlows()
注意:
SwiftUI
的.onAppear {}
與UIKit
的viewDidAppear(_ :)
基本相同狠怨。
當(dāng)視圖出現(xiàn)時(shí),您希望iOS同時(shí)檢查Apple ID
和iCloud
鑰匙串以查找與此應(yīng)用程序相關(guān)的憑據(jù)邑遏。 如果存在取董,則將自動(dòng)顯示Sign In with Apple
對話框,因此用戶不必手動(dòng)按下按鈕无宿。 由于同時(shí)按下按鈕和自動(dòng)調(diào)用都共享代碼茵汰,因此將showAppleLogin
方法重構(gòu)為兩種方法:
private func showAppleLogin() {
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email]
performSignIn(using: [request])
}
private func performSignIn(using requests: [ASAuthorizationRequest]) {
appleSignInDelegates = SignInWithAppleDelegates() { success in
if success {
// update UI
} else {
// show the user an error
}
}
let controller = ASAuthorizationController(authorizationRequests: requests)
controller.delegate = appleSignInDelegates
controller.performRequests()
}
除了將代理的創(chuàng)建和顯示移至其自己的方法之外,沒有任何代碼更改孽鸡。
現(xiàn)在蹂午,實(shí)現(xiàn)performExistingAccountSetupFlows()
:
private func performExistingAccountSetupFlows() {
// 1
#if !targetEnvironment(simulator)
// 2
let requests = [
ASAuthorizationAppleIDProvider().createRequest(),
ASAuthorizationPasswordProvider().createRequest()
]
// 2
performSignIn(using: requests)
#endif
}
這里只有幾個(gè)步驟:
- 1) 如果您使用的是模擬器,則什么也不做彬碱。如果您進(jìn)行這些調(diào)用豆胸,模擬器將打印出錯(cuò)誤。
- 2) 要求
Apple
提出對Apple ID
和iCloud
鑰匙串檢查的請求巷疼。 - 3) 調(diào)用您現(xiàn)有的安裝代碼晚胡。
請注意,在第2步中嚼沿,您沒有指定要檢索哪些最終用戶詳細(xì)信息估盘。回想一下本教程的前面部分骡尽,您在該教程中了解到遣妥,僅一次提供了詳細(xì)信息。由于此流程用于檢查現(xiàn)有帳戶攀细,因此無需指定requestedScopes
屬性箫踩。實(shí)際上爱态,如果您在此處設(shè)置了它,它將被忽略境钟!
Web Credentials
如果您有專門針對您的應(yīng)用程序的網(wǎng)站锦担,則可以走做的更多,也可以處理Web
憑據(jù)慨削。如果您查看UserAndPassword.swift
吆豹,則會(huì)看到對SharedWebCredential(domain :)
的調(diào)用,該調(diào)用當(dāng)前向構(gòu)造函數(shù)發(fā)送一個(gè)空字符串理盆。將其替換為您的網(wǎng)站域痘煤。
現(xiàn)在,登錄到您的網(wǎng)站猿规,并在網(wǎng)站的根目錄下創(chuàng)建一個(gè)名為.well-known
的目錄衷快。在其中創(chuàng)建一個(gè)名為apple-app-site-association
的新文件,并粘貼以下JSON
:
{
"webcredentials": {
"apps": [ "ABCDEFGHIJ.com.raywenderlich.SignInWithApple" ]
}
}
注意:確保文件名沒有擴(kuò)展名姨俩。
您需要將ABCDEFGHIJ
替換為團(tuán)隊(duì)的10個(gè)字符的Team ID
蘸拔。 您可以在Membership
選項(xiàng)卡下的https://developer.apple.com/account中找到您的Team ID
。 您還需要使bundle identifier
與您用于該應(yīng)用程序的標(biāo)識符匹配环葵。
通過執(zhí)行這些步驟调窍,您已將Safari
存儲(chǔ)的登錄詳細(xì)信息與應(yīng)用程序的登錄詳細(xì)信息相關(guān)聯(lián)。 它們現(xiàn)在可用于Sign in with Apple
张遭。
當(dāng)用戶手動(dòng)輸入用戶名和密碼時(shí)邓萨,將存儲(chǔ)憑據(jù),以便以后使用菊卷。
Runtime Checks
在應(yīng)用程序生命周期內(nèi)的任何時(shí)候缔恳,用戶都可以進(jìn)入設(shè)備設(shè)置并為您的應(yīng)用程序禁用Sign In with Apple
。 您將根據(jù)要執(zhí)行的操作檢查它們是否仍在登錄洁闰。Apple建議您運(yùn)行以下代碼:
let provider = ASAuthorizationAppleIDProvider()
provider.getCredentialState(forUserID: "currentUserIdentifier") { state, error in
switch state {
case .authorized:
// Credentials are valid.
break
case .revoked:
// Credential revoked, log them out
break
case .notFound:
// Credentials not found, show login UI
break
}
}
蘋果公司表示歉甚,getCredentialState(forUserId :)
調(diào)用非常快扑眉。 因此纸泄,您應(yīng)該在應(yīng)用啟動(dòng)期間以及需要確保用戶仍然通過身份驗(yàn)證的任何時(shí)間運(yùn)行它。 我建議您除非必須腰素,否則不要在應(yīng)用程序啟動(dòng)時(shí)運(yùn)行聘裁。 您的應(yīng)用真的需要登錄或注冊用戶才能使用嗎? 在他們嘗試執(zhí)行實(shí)際上需要登錄的操作之前耸弄,無需他們登錄咧虎。實(shí)際上,甚至Human Interface Guidelines也建議這樣做计呈!
請記住砰诵,如果要求他們做的第一件事是注冊,那么許多用戶將卸載剛剛下載的應(yīng)用程序捌显。
相反茁彭,請監(jiān)聽Apple提供的通知以了解用戶何時(shí)登出。 只需偵聽ASAuthorizationAppleIDProvider.credentialRevokedNotification
通知并采取適當(dāng)?shù)拇胧?/p>
The UIWindow
至此扶歪,您已經(jīng)完全實(shí)現(xiàn)了Sign In with Apple
理肺。 恭喜你!
如果您觀看了有關(guān)使用Apple登錄的WWDC演示文稿善镰,或者已閱讀其他教程妹萨,則可能會(huì)發(fā)現(xiàn)這里缺少一塊。 您從未實(shí)現(xiàn)過ASAuthorizationControllerPresentationContextProviding
代理方法來告訴iOS
使用哪個(gè)UIWindow
炫欺。 從技術(shù)上講乎完,如果您使用默認(rèn)的UIWindow
并不是必需的,那么最好知道如何處理品洛。
如果您不使用SwiftUI
树姨,那么從SceneDelegate
中獲取window
屬性并返回值非常簡單。 在SwiftUI
中桥状,它變得更加困難帽揪。
The Environment
SwiftUI
的新概念是Environment
。 在該區(qū)域中辅斟,您可以存儲(chǔ)需要用于許多SwiftUI
視圖的數(shù)據(jù)转晰。 在某種程度上,您可以將其視為依賴注入士飒。
1. Environment Setup
看一下EnvironmentWindowKey.swift
挽霉,您將看到在SwiftUI
環(huán)境中存儲(chǔ)值所需的代碼。 它是樣板代碼变汪,其中您定義了要傳遞給@Environment
屬性包裝器的鍵以及要存儲(chǔ)的值侠坎。 請注意,由于存儲(chǔ)了類的類型裙盾,因此如何將其顯式標(biāo)記為weak
引用以防止循環(huán)引用实胸。
注意:環(huán)境代碼是由
WWDC
實(shí)驗(yàn)室中的Apple
工程師提供的
2. ContentView Changes
跳回到ContentView.swift
并在ContentView
的頂部添加另一個(gè)屬性:
@Environment(\.window) var window: UIWindow?
iOS會(huì)自動(dòng)使用存儲(chǔ)在環(huán)境中的值填充window
變量。
在performSignIn(using :)
中番官,修改構(gòu)造函數(shù)調(diào)用以傳遞window
屬性:
appleSignInDelegates = SignInWithAppleDelegates(window: window) { success in
您還需要告訴ASAuthorizationController
將您的類用于presentationContextProvider
代理庐完,因此請?jiān)诜峙?code>controller.delegate后立即添加以下代碼。
controller.presentationContextProvider = appleSignInDelegates
3. Update the Delegate
打開SignInWithAppleDelegates.swift
處理新屬性徘熔,并對類進(jìn)行構(gòu)造函數(shù)更改门躯。 使用以下所有類的注冊和委托方法而不是擴(kuò)展替換類定義:
class SignInWithAppleDelegates: NSObject {
private let signInSucceeded: (Bool) -> Void
// 1
private weak var window: UIWindow!
// 2
init(window: UIWindow?, onSignedIn: @escaping (Bool) -> Void) {
// 3
self.window = window
self.signInSucceeded = onSignedIn
}
}
只是一些更改:
- 1) 存儲(chǔ)新的對
window
的weak
引用。 - 2) 將
UIWindow
參數(shù)作為第一個(gè)參數(shù)添加到初始化程序酷师。 - 3) 將傳入的值存儲(chǔ)到屬性讶凉。
最后染乌,實(shí)現(xiàn)新的代理類型:
extension SignInWithAppleDelegates:
ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController)
-> ASPresentationAnchor {
return self.window
}
}
代理只有一種方法可以實(shí)現(xiàn),該方法可以返回window
懂讯,該窗口顯示Sign In with Apple
模式對話框荷憋。
4. Update the Scene
將UIWindow
放入環(huán)境是最后要做的事。 打開SceneDelegate.swift
并替換以下行:
window.rootViewController = UIHostingController(rootView: ContentView())
用下面內(nèi)容
// 1
let rootView = ContentView().environment(\.window, window)
// 2
window.rootViewController = UIHostingController(rootView: rootView)
只需兩個(gè)小步驟即可完成所有操作:
- 1) 您創(chuàng)建
ContentView
并附加window
變量的值褐望。 - 2) 您將該
rootView
變量傳遞給UIHostingController
而不是舊的初始化程序勒庄。
environment
方法會(huì)返回some View
,這基本上意味著它將使用您的ContentView
瘫里,將您傳遞的值推入該視圖的環(huán)境中实蔽,然后將ContentView
返回給您。 現(xiàn)在谨读,從ContentView
呈現(xiàn)的任何SwiftUI
View
也會(huì)在其環(huán)境中保留該值局装。
如果您在其他任何地方創(chuàng)建新的根視圖,則該根將不包含環(huán)境值漆腌,除非您也明確地將它們返回贼邓。
Logins Do not Scroll
使用Apple
登錄時(shí)要記住的一個(gè)缺點(diǎn)是,iOS
顯示的window
不會(huì)滾動(dòng)闷尿! 對于大多數(shù)用戶而言塑径,這無關(guān)緊要,但是請務(wù)必注意填具。 例如统舀,作為我的應(yīng)用程序使用的網(wǎng)站的所有者,我擁有許多登錄名劳景。 我不僅可以自己登錄應(yīng)用程序誉简,而且還可以登錄SQL
數(shù)據(jù)庫,PHP
管理站點(diǎn)等盟广。
如果您登錄的次數(shù)過多闷串,則最終用戶可能看不到他們的實(shí)際需求。 嘗試確保將應(yīng)用程序鏈接到網(wǎng)站時(shí)筋量,該網(wǎng)站僅具有對應(yīng)用程序重要的登錄信息烹吵。 不要將所有應(yīng)用捆綁在一個(gè)域中。
后記
本篇主要講述了使用SwiftUI進(jìn)行蘋果登錄桨武,感興趣的給個(gè)贊或者關(guān)注~~~