How to bind an image to the next view in SwiftUI? - ios

trying to create an onboarding flow of views with text fields to capture profile data and in the last view I will store the data in Firestore. However, need to pass all the data down to the last view to register the user with this data.
View 0 has Username, email, and password
View 1 has first name, last name and image
View 2 has Job title, company name
I am able to pass the username, email, and password to view 1 and first name, last name, and image to view 2.
I am NOT able to pass the image to view 3 because it is now binding and is asking for an argument in the "Preview" that I can't figure out.
The String bindings I pass with .constant("") BUT what do I do to pass the image see code below.
```
import SwiftUI
struct Step1: View {
#State var firstname = ""
#State var lastname = ""
#Binding var email: String
#Binding var password:String
#Binding var username: String
#State var image: Image?
#State var showImagePicker = false
#State private var selectedImage: UIImage?
var body: some View {
VStack{
HStack{
VStack(alignment: .leading, spacing: 4) {
Text("Create profile")
.font(.system(size: 30))
.fontWeight(.bold)
Text("Basic profile information")
.font(.system(size: 18))
}
.padding(.horizontal, 32)
.padding(.bottom, 50)
.padding(.top, 50)
Spacer()
}
VStack(spacing: 20){
HStack{
if image != nil {
image?
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
.clipShape(RoundedRectangle(cornerRadius: 10.0))
} else {
Image("upload")
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
.clipShape(RoundedRectangle(cornerRadius: 10.0))
}
Spacer()
}
.onTapGesture {
self.showImagePicker = true
}
CustomTextField(text: $firstname, placeholder: Text("First name"), ImageName: "person")
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.2611568921)))
.cornerRadius(10)
CustomTextField(text: $lastname, placeholder: Text("Last name"), ImageName: "person")
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.2611568921)))
.cornerRadius(10)
}
.padding(.horizontal, 32)
Spacer()
NavigationLink(
destination: Step2(firstname: $email, lastname: $password, email: $username, password: $firstname, username: $lastname, image: $image)
.navigationBarBackButtonHidden(true)
.navigationTitle("")
.navigationBarHidden(true),
label: {
Text("Sign Up")
.font(.headline)
.foregroundColor(.white)
.frame(width:360, height: 50)
.background(Color(#colorLiteral(red: 0.03573478386, green: 0.4008729458, blue: 0.7616711259, alpha: 1)))
.cornerRadius(10)
.padding()
Spacer()
})
.navigationTitle("")
.navigationBarHidden(true)
}.sheet(isPresented: $showImagePicker, onDismiss: loadImage) {
ImagePicker(image: self.$selectedImage)
}
}
func loadImage() {
guard let selectedImage = selectedImage else { return }
image = Image(uiImage: selectedImage)
}
}
struct Step1_Previews: PreviewProvider {
static var previews: some View {
Step1(email: .constant(""), password: .constant(""), username: .constant(""))
}
}
```
```
import SwiftUI
struct Step2: View {
#Binding var firstname: String
#Binding var lastname: String
#Binding var email: String
#Binding var password:String
#Binding var username: String
#Binding var image: Image?
var body: some View {
VStack{
HStack{
VStack(alignment: .leading, spacing: 4) {
Text("Create profile")
.font(.system(size: 30))
.fontWeight(.bold)
Text("Basic profile information")
.font(.system(size: 18))
}
.padding(.horizontal, 32)
.padding(.bottom, 50)
.padding(.top, 50)
Spacer()
}
VStack(spacing: 20){
CustomTextField(text: $firstname, placeholder: Text("First name"), ImageName: "person")
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.2611568921)))
.cornerRadius(10)
CustomTextField(text: $lastname, placeholder: Text("Last name"), ImageName: "person")
.padding()
.background(Color(#colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 0.2611568921)))
.cornerRadius(10)
}
.padding(.horizontal, 32)
Spacer()
.navigationTitle("")
.navigationBarHidden(true)
}
}
}
struct Step2_Previews: PreviewProvider {
static var previews: some View {
Step2(firstname: .constant(""), lastname: .constant(""), email: .constant(""), password: .constant(""), username: .constant(""), image: WHAT TO PUT HERE????)
}
}
```

You can use .constant(Image(uiImage: UIImage())) or set any static image like this .constant(Image("image_name")))

Related

How to close sheet view with buttons

I'm currently running into a problem with a sheet not closing when the close button is pushed or the save button has completed transferring the data from the form to the list in homeview. Below is the code for a custom tab bar that when "New Survey" is pushed it will open the formView. The formView has two buttons closed and save. I would like it that when either one of these buttons are selected that it closes the formView.
struct FormView: View {
#Binding var surveys: [Survey]
#State var customerName = ""
#State var city = ""
#State var state = ""
#State var lineName = ""
#State var date = Date()
#Binding var isPresented: Bool
#State var showingFormView = false
var body: some View {
VStack{
ZStack {
NavigationView {
VStack {
ZStack {
Form {
Section(header: Text("Survey Info").font(.custom("Roboto-Light", size: 24)).foregroundColor(Color(red: 0.00, green: 0.188, blue: 0.42)).offset(x: -20)) { TextField("Customer Name", text: $customerName)
.padding(.vertical, 10.0)
.font(.custom("Roboto-Light", size: 18))
TextField("Customer City", text: $city)
.padding(.vertical, 10.0)
.font(.custom("Roboto-Light", size: 18))
TextField("State", text: $state)
.padding(.vertical, 10.0)
.font(.custom("Roboto-Light", size: 18))
TextField("Line Name", text: $lineName)
.padding(.vertical, 10.0)
.font(.custom("Roboto-Light", size: 18))
DatePicker("Date", selection: $date, displayedComponents: .date)
.padding(.vertical, 10.0)
.font(.custom("Roboto-Light", size: 18))
}
}
VStack (alignment: .center){
Spacer()
HStack {
**Button(action: {
self.showingFormView = false
self.isPresented = false
}, label: {
Text("Close")
.font(.custom("Roboto-Light", size: 23))
.foregroundColor(Color.white)
.frame(width: 150.0, height: 50.0, alignment: .center)
.background(Color(hue: 0.001, saturation: 0.768, brightness: 0.975))
.cornerRadius(3)
})
Button(action: {
// Save survey data to UserDefaults or any other means
let survey = Survey(customerName: customerName, city: city, state: state, lineName: lineName, date: date)
self.surveys.append(survey)
// Clear text fields
self.customerName = ""
self.city = ""
self.state = ""
self.lineName = ""
self.date = Date()
// Close FormView
self.showingFormView = false
self.isPresented = false
}, label: {
Text("Save")
.font(.custom("Roboto-Light", size: 23))
.foregroundColor(Color.white)
.frame(width: 150.0, height: 50.0, alignment: .center)
.background(Color(red: 0.451, green: 0.729, blue: 0.251))
.cornerRadius(3)
})**
}
}
}
}
.navigationBarHidden(true)
}
}
}
}
}
Custom Tab Bar
struct CustomTabBar: View {
#Binding var surveys: [Survey]
#Binding var isPresented : Bool
#State var showingFormView = false
var body: some View {
NavigationView{
VStack {
Spacer()
HStack (alignment: .bottom) {
Button {
} label: {
GeometryReader { geo in
VStack (alignment: .center, spacing: 4) {
Image(systemName: "magnifyingglass")
.resizable()
.scaledToFit()
.frame(width: 32, height: 32)
Text("Search")
.font(.custom("Roboto-Light", size: 14))
}
.frame(width: geo.size.width,height: geo.size.height)
}
}
.tint(Color(red: 0.0, green: 0.188, blue: 0.42))
**Button(action: {
showingFormView = true
}) {
GeometryReader { geo in
VStack(alignment: .center, spacing: 4) {
Image("PSIcon")
.resizable()
.scaledToFit()
.frame(width: 38, height: 38)
Text("New Survey")
.font(.custom("Roboto-Light", size: 14))
.tint(Color(red: 0.0, green: 0.188, blue: 0.42))
}
.frame(width: geo.size.width, height: geo.size.height)
}
}
.sheet(isPresented: $showingFormView) {
FormView(surveys: $surveys, isPresented: $isPresented) }
//code allows you to call up a specific view so long as a var is indicated
**
Button {
} label: {
GeometryReader { geo in
VStack (alignment: .center, spacing: 4) {
Image(systemName: "arrow.up.arrow.down")
.resizable()
.scaledToFit()
.frame(width: 35, height: 35)
Text("Sort")
.font(.custom("Roboto-Light", size: 14))
}
.frame(width: geo.size.width,height: geo.size.height)
}
}
.tint(Color(red: 0.0, green: 0.188, blue: 0.42))
}
.frame(height: 50.0)
}
}
}
}
The save button saves and creates a new item in the dynamic list but it does not close the formView. The only way for me to close the view is by swiping down on the screen.

SwiftUI: #State variable does not update View when its value changes (within same View)

I am very new to SwiftUI. Maybe I am not completely understanding how #State annotated variables work. As far as I know, when you update their values, if they're within the same View, the screen will get updated too (in this case the background color of the screen). I think I followed exactly the video tutorial (SwiftUI Basics Tutorial) but nonetheless I did not get my code to work. By the way, I'm using Xcode Version 13.2.1, if it's worth mentioning. In my ContentView.swift this is what I have:
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
#State private var isNight = false //Variable to be changed when pressing the button
var body: some View {
ZStack {
//The BackgroundView color should change when pressing the button
BackgroundView(topColor: isNight ? .black : .blue,
bottomColor: isNight ? .gray : Color("lightBlue"))
VStack{
CityTextView(cityName: "Cupertino, CA")
MainWeatherStatusView(imageName: "cloud.sun.rain.fill",
temperature: 72)
HStack(spacing: 0){
WeatherView(dayOfWeek: "TUE",
imageName: "cloud.sun.fill",
temperature: 74)
WeatherView(dayOfWeek: "WED",
imageName: "sun.max.fill",
temperature: 30)
WeatherView(dayOfWeek: "THU",
imageName: "wind.snow",
temperature: 5)
WeatherView(dayOfWeek: "FRI",
imageName: "sunset.fill",
temperature: 60)
WeatherView(dayOfWeek: "SAT",
imageName: "snow",
temperature: 74)
}
Button{
isNight.toggle() //Changing this should update my View, right?
} label: {
WeatherButton(title: "Change Day Time",
textColor: .blue,
backgroundColor: .white)
}
Spacer()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct WeatherView: View {
var dayOfWeek: String
var imageName: String
var temperature: Int
var body: some View {
VStack{
Text(dayOfWeek)
.font(.system(size: 15, weight: .medium, design: .default))
.foregroundColor(.white)
.padding()
Image(systemName: imageName)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40, height: 40)
Text("\(temperature)°")
.font(.system(size: 30, weight: .medium))
.foregroundColor(.white)
Spacer()
}
}
}
struct BackgroundView: View {
var topColor: Color
var bottomColor: Color
var body: some View {
LinearGradient(gradient: Gradient(colors: [.blue, Color("lightBlue")]), startPoint: .topLeading, endPoint: .bottomTrailing)
.edgesIgnoringSafeArea(.all)
}
}
struct CityTextView: View {
var cityName: String
var body: some View {
Text(cityName)
.font(.system(size: 32, weight: .medium, design: .default))
.foregroundColor(.white)
.padding()
}
}
struct MainWeatherStatusView: View {
var imageName: String
var temperature: Int
var body: some View {
VStack(spacing: 8){
Image(systemName: imageName)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 180, height: 180)
Text("\(temperature)°")
.font(.system(size: 70, weight: .medium))
.foregroundColor(.white)
}
}
}
In case you want to copy paste the code and want to get rid of the icons, here's the code without them:
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
#State private var isNight = false //VARIABLE TO BE CHANGED WHEN PRESSING BUTTON
var body: some View {
ZStack {
//The BackgroundView color should change when pressing the button
BackgroundView(topColor: isNight ? .black : .blue,
bottomColor: isNight ? .gray : Color("lightBlue"))
VStack{
CityTextView(cityName: "Cupertino, CA")
Button{
isNight.toggle() //CHANGING THIS SHOULD UPDATE MY VIEW, RIGHT?
} label: {
WeatherButton(title: "Change Day Time",
textColor: .blue,
backgroundColor: .white)
}
Spacer()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct WeatherView: View {
var dayOfWeek: String
var imageName: String
var temperature: Int
var body: some View {
VStack{
Text(dayOfWeek)
.font(.system(size: 15, weight: .medium, design: .default))
.foregroundColor(.white)
.padding()
Image(systemName: imageName)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40, height: 40)
Text("\(temperature)°")
.font(.system(size: 30, weight: .medium))
.foregroundColor(.white)
Spacer()
}
}
}
struct BackgroundView: View {
var topColor: Color
var bottomColor: Color
var body: some View {
LinearGradient(gradient: Gradient(colors: [.blue, Color("lightBlue")]), startPoint: .topLeading, endPoint: .bottomTrailing)
.edgesIgnoringSafeArea(.all)
}
}
struct CityTextView: View {
var cityName: String
var body: some View {
Text(cityName)
.font(.system(size: 32, weight: .medium, design: .default))
.foregroundColor(.white)
.padding()
}
}
struct MainWeatherStatusView: View {
var imageName: String
var temperature: Int
var body: some View {
VStack(spacing: 8){
Image(systemName: imageName)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 180, height: 180)
Text("\(temperature)°")
.font(.system(size: 70, weight: .medium))
.foregroundColor(.white)
}
}
}
In your current BackgroundView code, although you have topColor and bottomColor parameters, you don't actually use them in your view. You probably want to include them in your gradient:
struct BackgroundView: View {
var topColor: Color
var bottomColor: Color
var body: some View {
LinearGradient(gradient: Gradient(colors: [topColor, bottomColor]), startPoint: .topLeading, endPoint: .bottomTrailing)
.edgesIgnoringSafeArea(.all)
}
}
Also, make sure you have your custom colors (like Color("lightBlue")) in your asset catalogue.

Why ViewModel function is throwing error in SwiftUI?

I am trying to call ViewModel method in the view but getting error as Thread 1: Fatal error: No ObservableObject of type AuthViewModel found. A View.environmentObject(_:) for AuthViewModel may be missing as an ancestor of this view. I don't have any idea why it is happening.
AuthViewModel
import SwiftUI
class AuthViewModel: ObservableObject {
func login() {
print("Hello")
}
}
My View File
//
// RegistrationView.swift
// TwitterSwiftUI
//
// Created by developer on 11/06/21.
//
import SwiftUI
struct RegistrationView: View {
#State var text = ""
#State var fullName = ""
#State var userName = ""
#State var password = ""
#State var isImagePickerDisplay = false
#State var selectedImage:UIImage?
#Environment(\.presentationMode) var mode: Binding<PresentationMode>
#EnvironmentObject var viewModel: AuthViewModel
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.2203325033, green: 0.6315936446, blue: 0.955042541, alpha: 1))
.ignoresSafeArea()
VStack {
Button(action: {
isImagePickerDisplay = true
}, label: {
if selectedImage != nil {
Image(uiImage: selectedImage!)
.resizable()
.scaledToFit()
.frame(width: 140, height: 140)
.padding(.top, 0)
} else {
Image("plus_photo")
.resizable()
.renderingMode(/*#START_MENU_TOKEN#*/.template/*#END_MENU_TOKEN#*/)
.foregroundColor(.white)
.scaledToFit()
.frame(width: 140, height: 140)
.padding(.top, 0)
}
})
VStack {
CustomTextField(text: $fullName, placeholder: Text("Full name"), icon: Image(systemName: "person"))
.foregroundColor(.white)
.padding()
.background(Color(.init(white: 1, alpha: 0.15)))
.cornerRadius(10)
CustomTextField(text: $fullName, placeholder: Text("Email"), icon: Image(systemName: "envelope"))
.foregroundColor(.white)
.padding()
.background(Color(.init(white: 1, alpha: 0.15)))
.cornerRadius(10)
CustomTextField(text: $userName, placeholder: Text("Username"), icon: Image(systemName: "person"))
.foregroundColor(.white)
.padding()
.background(Color(.init(white: 1, alpha: 0.15)))
.cornerRadius(10)
CustomSecureField(password: $password)
.foregroundColor(.white)
.padding()
.background(Color(.init(white: 1, alpha: 0.15)))
.cornerRadius(10)
Spacer()
.frame(height: 30)
GeometryReader { geometry in
Button(action: {
//viewModel.registerUser(email: "userName", password: "password", userName: "userName", fullName: "fullName", profileImage: selectedImage)
viewModel.login()
}, label: {
Text("Sign up")
})
.frame(width: (geometry.size.width*1), height: 50)
.background(Color.white)
.clipShape(Capsule())
.padding(.vertical)
}
}.padding()
Spacer()
HStack {
Text("Already have account? Login in")
.foregroundColor(.white)
}.onTapGesture {
mode.wrappedValue.dismiss()
}.padding(.bottom, 28)
}
}.sheet(isPresented: self.$isImagePickerDisplay) {
ImagePickerViewHelper(selectedImage: self.$selectedImage, sourceType: .photoLibrary)
}
}
}
The error message clearly says that the #EnvironmentObject property wrapper requires the associated object to be added to the environment somewhere on a higher level of the view hierarchy with the environmentObject() modifier.
To access the view model directly you have to use #Stateobject to create an instance of the observed class
#Stateobject var viewModel = AuthViewModel()

iOS: How to make my image logo at the top of the page SwiftUI

firstly I am really new to iOS development and Swift (2 weeks coming here from PHP :))
I am building my simple Login page and wondering how to make my Logo image at the top of the page. Also I am wondering if I have done my layout wrong to get the desired layout as in the screenshot. Would appreciate the help on this.
(Logo scribbled out in the screen shot needs to go to the top outside the white background)
Thanks
LoginView:
import SwiftUI
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack {
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
Image("logo")
.resizable()
.scaledToFit()
Divider()
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding(.top, 0)
.padding(.bottom, 20)
}
.padding(.horizontal, CGFloat(verticalPaddingForForm))
.background(Color(.white))
VStack{
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.background(Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0))
.foregroundColor(Color.white)
.cornerRadius(10)
.padding()
}
}.ignoresSafeArea()
};
}
ContentView:
import SwiftUI
struct ContentView: View {
var body: some View {
LoginView()
}
}
extension UIDevice {
var hasNotch: Bool {
let bottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
return bottom > 0
}
}
Try below code-:
Use a ZStack to give a backgroundColor to your view, and give that a modifier of .ignoresSafeArea().
Use VStack inside ZStack to layout other view components. I have done few modifications on my side.
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack() {
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0).ignoresSafeArea()
VStack(spacing:15){
Image(systemName: “logo")
.resizable()
.scaledToFit()
.frame( height: 200)
.foregroundColor(Color.white)
.padding([.top],15)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
.padding([.top])
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: {}) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding([.bottom])
}
.background(Color(.white))
Spacer()
Button(action: {}) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.foregroundColor(Color.white)
.cornerRadius(10)
}
}
};
}
struct Test1: View {
var body: some View {
LoginView()
}
}
extension UIDevice {
var hasNotch: Bool {
let bottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
return bottom > 0
}
}
You can use ZStack (alignment: .top) to set the alignment from the top. And then you can use a Spacer() at the end of the second VStack to expand the view.
The following code works for me. It's your code with little changes. Also, I suggest you create a subview to better organize your code, instead of writing all views within the same view.
import SwiftUI
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
var body: some View {
ZStack (alignment: .top){
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
Image(systemName: "gear")
.resizable()
.scaledToFit()
.frame(width: 100)
Divider()
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
SecureField("Password", text: $password)
.padding(.horizontal, 30).padding(.top, 20)
Divider()
.padding(.horizontal, 30)
}
.background(Color(.white))
Text("Forgotten Password")
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding(.top, 0)
.padding(.bottom, 20)
Spacer()
}
.padding(.horizontal, CGFloat(verticalPaddingForForm))
.background(Color(.white))
VStack{
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.background(Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0))
.foregroundColor(Color.white)
.cornerRadius(10)
.padding()
}
}
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
Just put Spacer() between Image("logo") and Divider() to push your logo to the top of the screen

iOS: How to switch views from Login to Main Content SwiftUi

firstly I am really new to iOS development and Swift (2 weeks coming here from PHP :))
I am build a simple application, when the user Logs (Is confirmed) the view switched to the main content.
So currently I have a LoginView() and that is what loads first. I am wondering how when I click the Login button in LoginView() then the view switches to the MainContentView()
Any help would be appreciated. Thanks
LoginView()
'''
import SwiftUI
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
#State private var willMoveToNextScreen = true
var body: some View {
ZStack {
Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0)
VStack(alignment: .leading, spacing: 0) {
Image("logo")
.resizable()
.scaledToFit()
.padding(.top, 150)
.padding()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
.ignoresSafeArea(.all)
VStack(spacing: CGFloat(verticalPaddingForForm)) {
VStack {
TextField("Email", text: $email)
.padding(.horizontal, 15).padding(.top, 50)
Divider()
.padding(.horizontal, 15)
SecureField("Password", text: $password)
.padding(.horizontal, 15).padding(.top, 20)
Divider()
.padding(.horizontal, 15)
}
.background(Color(.white))
Link("Forgotten Password",
destination: URL(string: "https://www.google.co.uk")!)
.foregroundColor(.blue)
.font(.system(size: 15))
Button(action: {
//Do login stuff here and if true switch view to to MainContentView
}) {
Text("Login")
.padding()
.font(.system(size: 20))
}
.background(Color.black)
.foregroundColor(Color.white)
.cornerRadius(10)
.padding(.top, 0)
.padding(.bottom, 20)
}
.padding(.horizontal, CGFloat(verticalPaddingForForm))
.background(Color(.white))
VStack{
Spacer()
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Register")
.padding()
.font(.system(size: 40))
}
.background(Color(red: 20/225.0 ,green: 22/225.0 , blue: 25/225.0))
.foregroundColor(Color.white)
.cornerRadius(10)
.padding()
}
}.ignoresSafeArea()
};
}
'''
Below is the content view, the LoginView loads firsts and when the login button is click from above then should switch to the MainContentView() which is commented out below
ContentView:
'''
import SwiftUI
struct ContentView: View {
var body: some View {
LoginView()
//After login is confirmed in the login view, then switch from
// LoginView to
//MainContentView()
}
}
'''
You can have a State in the ContentView, which decides wheather your User is logged in.
struct ContentView: View {
#State var isLoggedIn: Bool = false
var body: some View {
if !isLoggedIn {
LoginView(isLoggedIn: $isLoggedIn)
} else {
MainContentView()
}
}
}
Then in the logging View add a Binding, and when the users successfully logged in, change that binding.
struct LoginView: View {
#State private var email: String = ""
#State private var password: String = ""
let verticalPaddingForForm = 40
#Binding var isLoggedIn: Bool // here is the Binding
Then in the Action, toggle that Binding
Button(action: {
//Do login stuff here and if true switch view to to MainContentView
isLoggedIn = true
You could also think using some kind of Navigation Pattern and pushing to the next view.
The code above is not tested, just out of my mind

Resources