SwiftUI iOS注册登录页:邮箱验证跳转新视图及代码优化求助
代码优化意见 & 跳转问题解决
一、代码优化点
- 命名规范修正:Swift变量遵循小驼峰命名,把
Error改为isEmailInvalid,ValidationButton直接用isEmailValid判断(省去冗余状态),提升代码可读性。 - 实时邮箱验证:当前仅在编辑结束时验证,改为监听输入实时响应,用户输入过程中就能得到反馈:
TextField("Email", text: $email) .onChange(of: email) { _ in isEmailInvalid = !isEmailValid } - 修复第三方按钮图标错误:Google、Facebook按钮误用了
apple.logo,需替换为对应图标(系统无内置的话要导入自定义资源)。 - 提取重复视图:把三个第三方登录按钮封装成自定义
SocialLoginButton,减少代码冗余:
使用时直接调用:struct SocialLoginButton: View { let iconName: String let action: () -> Void var body: some View { Button(action: action) { ZStack { RoundedRectangle(cornerRadius: 6) .fill(Color.systemGray5) Image(systemName: iconName) .font(.system(size: 19)) .foregroundColor(.primary) } } } }SocialLoginButton(iconName: "apple.logo", action: { print("Apple tapped") }) - 语义化颜色使用:把
Color(.systemGray5)改为Color.systemGray5,贴合SwiftUI写法规范。
二、邮箱验证后跳转实现
iOS 16+ 方案(推荐)
用.navigationDestination实现跳转,步骤如下:
- 添加导航状态变量:
@State private var shouldNavigateToNextScreen = false - 在
NavigationView的根VStack末尾添加导航目标:.navigationDestination(isPresented: $shouldNavigateToNextScreen) { // 替换成你已创建的目标视图,比如PasswordSetupView() Text("下一步:设置密码") } - 修改验证按钮的action:
if isEmailValid { Button(action: { shouldNavigateToNextScreen = true }) { Image(systemName: "arrow.forward.square.fill") .font(.system(size: 35)) } .padding(.leading, 8) }
iOS 15及以下方案
用NavigationLink结合isActive绑定:
- 添加导航状态变量:
@State private var shouldNavigateToNextScreen = false - 在
NavigationView的VStack中添加隐藏的NavigationLink:NavigationLink( destination: YourTargetView(), // 替换为你的目标视图 isActive: $shouldNavigateToNextScreen ) { EmptyView() } .hidden() - 同样在验证按钮的action中设置
shouldNavigateToNextScreen = true。
优化后的完整代码示例
import SwiftUI struct Registration: View { // MARK: - Properties @State private var email = "" @State private var isEmailInvalid = false @State private var shouldNavigateToNextScreen = false // Check email var isEmailValid: Bool { let emailRegex = #"^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"# return NSPredicate(format: "SELF MATCHES %@", emailRegex).evaluate(with: email) } // MARK: - Body var body: some View { NavigationView { VStack(alignment: .leading, spacing: 40) { VStack(spacing: 18) { VStack(alignment: .leading, spacing: 5) { Text("Welcome!") .font(.title) .fontWeight(.bold) Text("Enter your e-mail in order to log in or create an account") .multilineTextAlignment(.leading) } .frame(maxWidth: .infinity, alignment: .leading) HStack(spacing: 16) { Image(systemName: "envelope.fill") .imageScale(.large) .foregroundColor(.primary) TextField("Email", text: $email) .font(.system(size: 20)) .frame(maxWidth: .infinity, alignment: .leading) .foregroundColor(.primary) .onChange(of: email) { _ in isEmailInvalid = !isEmailValid } if isEmailValid { Button(action: { shouldNavigateToNextScreen = true }) { Image(systemName: "arrow.forward.square.fill") .font(.system(size: 35)) } .padding(.leading, 8) } } .padding(.horizontal, 16) .frame(minHeight: 55) .overlay( RoundedRectangle(cornerRadius: 6) .stroke(isEmailInvalid ? .red : .primary) ) if isEmailInvalid { Text("Please enter a valid email address") .foregroundColor(.red) .padding(.leading, 16) .frame(maxWidth: .infinity, alignment: .leading) } } .foregroundColor(.primary) HStack(spacing: 10) { Rectangle() .fill(Color.separator) .frame(height: 1) Text("or continue with") .fixedSize(horizontal: true, vertical: true) .frame(maxWidth: .infinity) Rectangle() .fill(Color.separator) .frame(height: 1) } HStack(alignment: .top, spacing: 12) { SocialLoginButton(iconName: "apple.logo") { print("Tap on Apple button") } // 注意:Google和Facebook需要替换为正确的图标 SocialLoginButton(iconName: "google") { print("Tap on Google button") } SocialLoginButton(iconName: "facebook") { print("Tap on Facebook button") } } .frame(maxHeight: 50) } .padding(.horizontal, 16) .background(Color.systemBackground) .navigationBarHidden(true) .navigationDestination(isPresented: $shouldNavigateToNextScreen) { // 替换成你的目标视图 Text("Next Registration Step") } } .navigationViewStyle(StackNavigationViewStyle()) } } struct SocialLoginButton: View { let iconName: String let action: () -> Void var body: some View { Button(action: action) { ZStack { RoundedRectangle(cornerRadius: 6) .fill(Color.systemGray5) Image(systemName: iconName) .font(.system(size: 19)) .foregroundColor(.primary) } } } } struct RegistrationView_Previews: PreviewProvider { static var previews: some View { Registration() } }
内容的提问来源于stack exchange,提问作者jules
相关产品推荐
相关产品推荐

