已验证用户访问主页,未验证用户留在登录状态
Verified users access home and unverified users stay in the login
我正在检查用户在登录功能中注册后是否收到验证邮件:
static func authenticate(withEmail email :String,
password:String,
completionHandler:@escaping (Result<Bool, EmailAuthError>) -> ()) {
Auth.auth().signIn(withEmail: email, password: password) { (authResult, error) in
// check the NSError code and convert the error to an AuthError type
var newError:NSError
if let err = error {
newError = err as NSError
var authError:EmailAuthError?
switch newError.code {
case 17009:
authError = .incorrectPassword
case 17008:
authError = .invalidEmail
case 17011:
authError = .accoundDoesNotExist
default:
authError = .unknownError
}
completionHandler(.failure(authError!))
} else {
if (Auth.auth().currentUser!.isEmailVerified == true){
completionHandler(.success(true))
print ("Email Verified")
}
else {
print ("Email not verified")
}
}
}
}
单击“登录”按钮后将调用此函数,我在此处重新加载用户以确保 (isEmailVerified) 值已更新。
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
self.authError = error
self.showAlert = true
case .success( _):
print ("Signed in.")
}
}
}
我正在检查用户登录状态的内容视图,我在将 isEmailVerified 添加到我的代码后没有更新它,因为我只有三种情况未定义,已签名,已签名,我不知道如何退出这个盒子的:
struct ContentView: View {
@EnvironmentObject var userInfo : UserInfo
@State var shouldShowSignUp : Bool = false
var body: some View {
Group {
if shouldShowSignUp {
SignupView()
}
else {
ZStack{
if userInfo.isUserAuthenticated == .undefined{ SignupView()}
else if userInfo.isUserAuthenticated == .signedIn && Auth.auth().currentUser!.isEmailVerified == true {HomeView()}
else if userInfo.isUserAuthenticated == .signedIn && Auth.auth().currentUser!.isEmailVerified == false {LoginView()}
SplashScreen()
}
}
}
.onAppear {
self.userInfo.configureFirebaseStateDidChange()
}
}}
用户信息:
import Foundation
import FirebaseAuth
class UserInfo : ObservableObject{
enum FBAuthState{
case undefined, signedOut, signedIn
}
@Published var isUserAuthenticated : FBAuthState = .undefined
@Published var user : FBUser = .init(uid: "", name: "", email: "")
var authStateDidChangeListenerHandle : AuthStateDidChangeListenerHandle?
func configureFirebaseStateDidChange (){
authStateDidChangeListenerHandle = Auth.auth().addStateDidChangeListener({ (_,user) in
guard let _ = user else {
self.isUserAuthenticated = .signedOut
return
}
self.isUserAuthenticated = .signedIn
})
}
}
一切顺利。我得到了 isEmailVerified 的正确值。我的问题是如何让经过验证的用户访问 homeView 和未经验证的用户,他们会收到他们的电子邮件需要验证的警报,并且他们会留在 loginView 中。
因为你没有post你的观点,所以我必须用一个抽象的答案来回答。
在您的主 App 结构中
@main
struct TestApp1App: App {
@Environment(\.scenePhase) private var scenePhase
@AppStorage("emailVerified") private var emailVerified: Bool = false
var body: some Scene {
WindowGroup {
if emailVerified{
LoginView()
}else{
HomeView()
}
}
}
}
并且在您的登录视图中:
// Add this
@AppStorage("emailVerified") private var emailVerified: Bool = false
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
self.authError = error
self.showAlert = true
case .success( _):
print ("Signed in.")
emailVerified = true //add this
}
}
}
编辑:
但这并没有改变我回答的主要布局。例如,您不保留 verificationState。所以你必须重新做一遍。
在你的情况下,在你的应用程序结构中创建 UserInfo
class 并检查 if 语句中的 isUserAuthenticated
属性。
编辑 2:
这可以通过多种方式简化。我的建议:
ContentView 应该是这样的:
struct ContentView: View {
@EnvironmentObject var userInfo : UserInfo
// pull the vars from persisted store this will also update your view when changed
@AppStorage("authState") var authState: FBAuthState = .undefined
@AppStorage("emailVerificationState") var emailVerificationState: Bool = false
var body: some View {
Group{
if authState == .undefined || !emailVerificationState{
SignupView()
} else {
ZStack{
if authState == .signedIn{
HomeView()
} else{
LoginView()
}
SplashScreen()
}
}
}
.onAppear {
self.userInfo.configureFirebaseStateDidChange()
}
}
}
将您的用户信息更改为:
enum FBAuthState: Int{
case undefined, signedOut, signedIn
}
class UserInfo : ObservableObject{
@AppStorage("authState") var authState: FBAuthState = .undefined
@Published var user : FBUser = .init(uid: "", name: "", email: "")
var authStateDidChangeListenerHandle : AuthStateDidChangeListenerHandle?
func configureFirebaseStateDidChange (){
authStateDidChangeListenerHandle = Auth.auth().addStateDidChangeListener({ (_,user) in
guard let _ = user else {
self.authState = .signedOut
return
}
self.authState = .signedIn
})
}
}
我不知道这个按钮在哪里,但在 class 或视图中添加:
@AppStorage("emailVerificationState") var emailVerificationState: Bool = false
并做:
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
emailVerificationState = false
self.authError = error
self.showAlert = true
case .success( _):
emailVerificationState = true
print ("Signed in.")
}
}
}
编辑 3:
- 您需要在要使用@AppStorage 属性 包装器的地方导入 SwiftUI 模块。
- 请看我的回答。我将 FBAuthState 移出您的 class 以使其在外部可见。你需要从
Int
. 派生
编辑 4:
Group{
if authState == .undefined {
SignupView()
} else {
ZStack{
if authState == .signedIn && emailVerificationState{
HomeView()
} else{
LoginView()
}
SplashScreen()
}
}
}
我正在检查用户在登录功能中注册后是否收到验证邮件:
static func authenticate(withEmail email :String,
password:String,
completionHandler:@escaping (Result<Bool, EmailAuthError>) -> ()) {
Auth.auth().signIn(withEmail: email, password: password) { (authResult, error) in
// check the NSError code and convert the error to an AuthError type
var newError:NSError
if let err = error {
newError = err as NSError
var authError:EmailAuthError?
switch newError.code {
case 17009:
authError = .incorrectPassword
case 17008:
authError = .invalidEmail
case 17011:
authError = .accoundDoesNotExist
default:
authError = .unknownError
}
completionHandler(.failure(authError!))
} else {
if (Auth.auth().currentUser!.isEmailVerified == true){
completionHandler(.success(true))
print ("Email Verified")
}
else {
print ("Email not verified")
}
}
}
}
单击“登录”按钮后将调用此函数,我在此处重新加载用户以确保 (isEmailVerified) 值已更新。
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
self.authError = error
self.showAlert = true
case .success( _):
print ("Signed in.")
}
}
}
我正在检查用户登录状态的内容视图,我在将 isEmailVerified 添加到我的代码后没有更新它,因为我只有三种情况未定义,已签名,已签名,我不知道如何退出这个盒子的:
struct ContentView: View {
@EnvironmentObject var userInfo : UserInfo
@State var shouldShowSignUp : Bool = false
var body: some View {
Group {
if shouldShowSignUp {
SignupView()
}
else {
ZStack{
if userInfo.isUserAuthenticated == .undefined{ SignupView()}
else if userInfo.isUserAuthenticated == .signedIn && Auth.auth().currentUser!.isEmailVerified == true {HomeView()}
else if userInfo.isUserAuthenticated == .signedIn && Auth.auth().currentUser!.isEmailVerified == false {LoginView()}
SplashScreen()
}
}
}
.onAppear {
self.userInfo.configureFirebaseStateDidChange()
}
}}
用户信息:
import Foundation
import FirebaseAuth
class UserInfo : ObservableObject{
enum FBAuthState{
case undefined, signedOut, signedIn
}
@Published var isUserAuthenticated : FBAuthState = .undefined
@Published var user : FBUser = .init(uid: "", name: "", email: "")
var authStateDidChangeListenerHandle : AuthStateDidChangeListenerHandle?
func configureFirebaseStateDidChange (){
authStateDidChangeListenerHandle = Auth.auth().addStateDidChangeListener({ (_,user) in
guard let _ = user else {
self.isUserAuthenticated = .signedOut
return
}
self.isUserAuthenticated = .signedIn
})
}
}
一切顺利。我得到了 isEmailVerified 的正确值。我的问题是如何让经过验证的用户访问 homeView 和未经验证的用户,他们会收到他们的电子邮件需要验证的警报,并且他们会留在 loginView 中。
因为你没有post你的观点,所以我必须用一个抽象的答案来回答。
在您的主 App 结构中
@main
struct TestApp1App: App {
@Environment(\.scenePhase) private var scenePhase
@AppStorage("emailVerified") private var emailVerified: Bool = false
var body: some Scene {
WindowGroup {
if emailVerified{
LoginView()
}else{
HomeView()
}
}
}
}
并且在您的登录视图中:
// Add this
@AppStorage("emailVerified") private var emailVerified: Bool = false
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
self.authError = error
self.showAlert = true
case .success( _):
print ("Signed in.")
emailVerified = true //add this
}
}
}
编辑:
但这并没有改变我回答的主要布局。例如,您不保留 verificationState。所以你必须重新做一遍。
在你的情况下,在你的应用程序结构中创建 UserInfo
class 并检查 if 语句中的 isUserAuthenticated
属性。
编辑 2:
这可以通过多种方式简化。我的建议:
ContentView 应该是这样的:
struct ContentView: View {
@EnvironmentObject var userInfo : UserInfo
// pull the vars from persisted store this will also update your view when changed
@AppStorage("authState") var authState: FBAuthState = .undefined
@AppStorage("emailVerificationState") var emailVerificationState: Bool = false
var body: some View {
Group{
if authState == .undefined || !emailVerificationState{
SignupView()
} else {
ZStack{
if authState == .signedIn{
HomeView()
} else{
LoginView()
}
SplashScreen()
}
}
}
.onAppear {
self.userInfo.configureFirebaseStateDidChange()
}
}
}
将您的用户信息更改为:
enum FBAuthState: Int{
case undefined, signedOut, signedIn
}
class UserInfo : ObservableObject{
@AppStorage("authState") var authState: FBAuthState = .undefined
@Published var user : FBUser = .init(uid: "", name: "", email: "")
var authStateDidChangeListenerHandle : AuthStateDidChangeListenerHandle?
func configureFirebaseStateDidChange (){
authStateDidChangeListenerHandle = Auth.auth().addStateDidChangeListener({ (_,user) in
guard let _ = user else {
self.authState = .signedOut
return
}
self.authState = .signedIn
})
}
}
我不知道这个按钮在哪里,但在 class 或视图中添加:
@AppStorage("emailVerificationState") var emailVerificationState: Bool = false
并做:
Button(action: {
//Sign In Action
FBAuth.reloadUser()
FBAuth.authenticate(withEmail: self.user.email, password: self.user.password) { (result) in
switch result {
case .failure(let error):
emailVerificationState = false
self.authError = error
self.showAlert = true
case .success( _):
emailVerificationState = true
print ("Signed in.")
}
}
}
编辑 3:
- 您需要在要使用@AppStorage 属性 包装器的地方导入 SwiftUI 模块。
- 请看我的回答。我将 FBAuthState 移出您的 class 以使其在外部可见。你需要从
Int
. 派生
编辑 4:
Group{
if authState == .undefined {
SignupView()
} else {
ZStack{
if authState == .signedIn && emailVerificationState{
HomeView()
} else{
LoginView()
}
SplashScreen()
}
}
}