Несколько нижних листов — содержимое не загружает SwiftUI

Я сделал вид с двумя возможными нижними листами. Действие работает, и нижние листы открываются. Сумасшествие в том, что они открываются без вида внутрь. Я должен закрыть тот, который я открыл, и открыть другой. Когда я это сделаю и вернусь к первому, я увижу содержимое. Код собирается без предупреждений:

LogInView — где логика:

import SwiftUI

struct LogInView: View {
    @EnvironmentObject var userInfo: UserInfo
    enum Action{
        case resetPW, signUp
    }
    @State private var showSheet = false
    @State private var action:Action?
    
    var body: some View {
        LoginEmailView(showSheet: $showSheet, action: $action)
            .sheet(isPresented: $showSheet){
                if self.action == .resetPW{
                    ModalResetPWView()
                }else if self.action == .signUp{
                    ModalSignUpView()
                }
                
            }
    }
}

Вид, из которого исходят действия:

import SwiftUI

struct LoginEmailView: View {
    
    @EnvironmentObject var userInfo: UserInfo
    @StateObject var user:LogInViewModel = LogInViewModel()
  
    
// ----- > THERE IS BINDING
    @Binding var showSheet: Bool
    @Binding var action:LogInView.Action?
// ----- >
    
    var body: some View {
        VStack{
            Spacer()
        Image("logo")
            HStack{
                Text("Adres email:")
                    .padding(.horizontal, 10)
                    .font(.title)
                    .foregroundColor(.black)
                Spacer()
            }
            
            TextField("Enter e-mail adress", text: self.$user.email)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .font(.title)
            .padding(.horizontal, 10)
                .keyboardType(.emailAddress)
            
            HStack{
               Text("Password:")
                    .padding(.horizontal, 10)
                    .font(.title)
                    .foregroundColor(.black)
                Spacer()
            }
            SecureField("Enter password", text: self.$user.password)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .font(.title)
            .padding(.horizontal,10)
            HStack{
                
                Spacer()
                
// ----- > First Bottom sheet
                Button(action: {
                    self.action = .resetPW
                    self.showSheet = true
                }) {
                    Text("Forgot Password")
                }
                .padding(.top, 5)
                .padding(.trailing, 10)
// ----- >                

            }
       
            
            
            Button(action: {
                self.userInfo.isAuthenticated = .signedIn
            }) {
                Text("Log in")
            }
            .font(.title)
            .padding(5)
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
            .padding(.top, 10)
            .opacity(user.isLogInComplete ? 1 : 0.7)
            .disabled(!user.isLogInComplete)
           
// ----- > Second bottom sheet
            Button(action: {
                self.action = .signUp
                self.showSheet = true
            }) {
                Text("Sign Up")
            }
// ----- >
          
            .padding(.top, 35)
            
            Spacer()
        }
        
    }
    
}

Внутри .sheet ваш оператор «if..else if» не улавливает «else» (ситуации, когда действие == nil). Вероятно, он возвращает EmptyView() на основе этого оператора if.

nicksarno 22.12.2020 23:39

@niksarno Да, это помогает! Но: swift var body: some View { LoginEmailView(showSheet: $showSheet, action: $action) .sheet(isPresented: $showSheet){ if self.action == .resetPW{ ModalResetPWView() }else { ModalSignUpView() } } } Теперь оба BottomSheets впервые показывают подписку :( Почему при первом запуске nil - есть действие, пройденное с открытием нижнего листа

Heldan 22.12.2020 23:49

Отвечает ли это на ваш вопрос? Несколько листов(isPresented:) не работают в SwiftUI

Curiosity 03.03.2021 00:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
535
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Модификатор .sheet создаст представление листа, как только будет инициализирован LogInView(). В вашем утверждении «if.. else if..» нет логики для улавливания «иначе» ситуаций (ситуаций, когда действие == nil). Следовательно, поскольку action == nil в init(), первый .sheet, который будет представлен, не выполнит ваш 'if..else if', и будет представлен EmptyView.

Но не волнуйтесь! Это распространенная проблема, и ее можно легко решить. Вот 2 простых способа реализовать методы, чтобы исправить это (я предпочитаю второй метод, потому что он чище):

МЕТОД 1: представьте одно представление и измените содержимое этого представления вместо того, чтобы переключаться между представлениями для представления.

Вместо того, чтобы выполнять оператор if.. else if.. в модификаторе .sheet, представьте статическое представление (я назвал его SecondaryView), которое имеет переменную @Binding, связанную с вашим действием. Таким образом, когда появляется LogInView(), мы можем гарантировать, что он обязательно отобразит это представление, а затем мы можем просто изменить содержимое этого представления, изменив действие @Binding.

import SwiftUI

struct LogInView: View {

    enum Action{
        case resetPW, signUp
    }

    @State private var showSheet = false
    @State private var action: Action?

    var body: some View {
        LoginEmailView(showSheet: $showSheet, action: $action)
            .sheet(isPresented: $showSheet) {
                SecondaryView(action: $action)
            }
    }
}

struct LoginEmailView: View {

    @Binding var showSheet: Bool
    @Binding var action: LogInView.Action?

    var body: some View {
        VStack(spacing: 40 ){

            Text("Forgot Password")
                .onTapGesture {
                    action = .resetPW
                    showSheet.toggle()
                }

            Text("Sign Up")
                .onTapGesture {
                    action = .signUp
                    showSheet.toggle()
                }
        }
    }
}

struct SecondaryView: View {

    @Binding var action: LogInView.Action?

    var body: some View {
        if action == .signUp {
            Text("SIGN UP VIEW HERE")
        } else {
            Text("FORGOT PASSWORD VIEW HERE")
        }
    }
}

МЕТОД 2: Сделайте каждую кнопку собственным представлением, чтобы она могла иметь свой собственный модификатор .sheet.

В SwiftUI мы ограничены одним модификатором .sheet() на представление. Тем не менее, мы всегда можем добавить представления внутри представлений, и тогда каждому подпредставлению также разрешен собственный модификатор .sheet(). Таким образом, простое решение состоит в том, чтобы сделать каждую из ваших кнопок отдельным представлением. Я предпочитаю этот метод, потому что нам больше не нужно передавать переменные @State/@Binding между представлениями.

struct LogInView: View {

    var body: some View {
        LoginEmailView()
    }
}

struct LoginEmailView: View {

    var body: some View {
        VStack(spacing: 40 ){
            ForgotPasswordButton()

            SignUpButton()
        }
    }
}

struct ForgotPasswordButton: View {

    @State var showSheet: Bool = false

    var body: some View {
        Text("Forgot Password")
            .onTapGesture {
                showSheet.toggle()
            }
            .sheet(isPresented: $showSheet, content: {
                Text("FORGOT PASSWORD VIEW HERE")
            })
    }
}

struct SignUpButton: View {

    @State var showSheet: Bool = false

    var body: some View {
        Text("Sign Up")
            .onTapGesture {
                showSheet.toggle()
            }
            .sheet(isPresented: $showSheet, content: {
                Text("SIGN UP VIEW HERE")
            })
    }
}

Другие вопросы по теме