I have register screen in SwiftUI, and I want to use two screen for register users, one view have mail and password, and other view have name surname and occupation, but I am still do not understand how I will connect both register view, any idea?
RegistrationViewModel:
enum RegistrationState {
case successfullyRegistered
case failed(error: Error)
case na
}
protocol RegistrationViewModel {
func create()
var service: RegistrationService { get }
var state: RegistrationState { get }
var hasError: Bool { get }
var newUser: RegistrationCredentials { get }
init(service: RegistrationService)
}
final class RegistrationViewModelImpl: ObservableObject, RegistrationViewModel {
let service: RegistrationService
@Published var state: RegistrationState = .na
@Published var newUser = RegistrationCredentials(email: "",
password: "",
firstName: "",
lastName: "",
occupation: "")
@Published var hasError: Bool = false
private var subscriptions = Set<AnyCancellable>()
init(service: RegistrationService) {
self.service = service
setupErrorSubscription()
}
func create() {
service
.register(with: newUser)
.sink { [weak self] res in
switch res {
case .failure(let error):
self?.state = .failed(error: error)
default: break
}
} receiveValue: { [weak self] in
self?.state = .successfullyRegistered
}
.store(in: &subscriptions)}}
private extension RegistrationViewModelImpl {
func setupErrorSubscription() {
$state
.map { state -> Bool in
switch state {
case .successfullyRegistered,
.na:
return false
case .failed:
return true}}
.assign(to: &$hasError)}}
firstscreen:
struct RegisterView: View {
@StateObject private var viewModel = RegistrationViewModelImpl(
service: RegistrationServiceImpl()
)
var body: some View {
NavigationView {
VStack(spacing: 32) {
VStack(spacing: 16) {
InputTextFieldView(text: $viewModel.newUser.email,
placeholder: "Email",
keyboardType: .emailAddress,
systemImage: "envelope")
InputPasswordView(password: $viewModel.newUser.password,
placeholder: "Password",
systemImage: "lock")
}
ButtonView(title: "Next") {
viewModel.create()
}
}
.padding(.horizontal, 15)
.alert(isPresented: $viewModel.hasError,
content: {
if case .failed(let error) = viewModel.state {
return Alert(
title: Text("Error"),
message: Text(error.localizedDescription))
} else {
return Alert(
title: Text("Error"),
message: Text("Something went wrong"))
}})}}}
secondscreen:
import SwiftUI
struct SecondRegisterView: View {
@StateObject private var viewModel = RegistrationViewModelImpl(
service: RegistrationServiceImpl()
)
var body: some View {
NavigationView {
VStack(spacing: 32) {
VStack(spacing: 16) {
InputTextFieldView(text: $viewModel.newUser.firstName,
placeholder: "First Name",
keyboardType: .namePhonePad,
systemImage: nil)
InputTextFieldView(text: $viewModel.newUser.lastName,
placeholder: "Last Name",
keyboardType: .namePhonePad,
systemImage: nil)
InputTextFieldView(text: $viewModel.newUser.occupation,
placeholder: "Occupation",
keyboardType: .namePhonePad,
systemImage: nil)
}
ButtonView(title: "Sign up") {
viewModel.create()
}
}
.padding(.horizontal, 15)
.navigationTitle("Register")
.applyClose()
.alert(isPresented: $viewModel.hasError,
content: {
if case .failed(let error) = viewModel.state {
return Alert(
title: Text("Error"),
message: Text(error.localizedDescription))
} else {
return Alert(
title: Text("Error"),
message: Text("Something went wrong"))
}
})
}
}
}