iOS SwiftUI: отображать или отклонять вид программно

Я не мог найти упоминание о каких - либо способах сделать попы или отклонить программно моего представленного вида с SwiftUI.

Мне кажется, что единственный способ - это использовать уже интегрированное слайд-действие для модального окна (и что/как, если я хочу отключить эту функцию?) И кнопку возврата для стека навигации.

Кто-нибудь знает решение? Вы знаете, если это ошибка или она останется такой?

Ответ 1

В этом примере используется новая среда var, задокументированная в примечаниях к выпуску Beta 5, в которой использовалось свойство value. Он был изменен в более поздней бета-версии для использования свойства wrappedValue. Этот пример сейчас актуален для версии GM. Эта та же самая концепция работает для отклонения модальных представлений, представленных с модификатором .sheet.

import SwiftUI

struct DetailView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var body: some View {
        Button(
            "Here is Detail View. Tap to go back.",
            action: { self.presentationMode.wrappedValue.dismiss() }
        )
    }
}

struct RootView: View {
    var body: some View {
        VStack {
            NavigationLink(destination: DetailView())
            { Text("I am Root. Tap for Detail View.") }
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            RootView()
        }
    }
}

Ответ 2

Теперь есть возможность программно вставлять в NavigationView, если хотите. Это бета-версия 5. Обратите внимание, что вам не нужна кнопка возврата. Вы можете программно вызвать свойство showSelf в DetailView любым удобным для вас способом. И вам не нужно отображать текст "Push" в мастере. Это может быть EmptyView(), что создает невидимый переход.

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            MasterView()
        }
    }
}

struct MasterView: View {
    @State var showDetail = false

    var body: some View {
        VStack {
            NavigationLink(destination: DetailView(showSelf: $showDetail), isActive: $showDetail) {
                Text("Push")
            }
        }
    }
}

struct DetailView: View {
    @Binding var showSelf: Bool

    var body: some View {
        Button(action: {
            self.showSelf = false
        }) {
            Text("Pop")
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

Ответ 3

Вы можете попробовать использовать пользовательский вид и Transition.

Здесь пользовательский модал.

struct ModalView<Content>: View where Content: View {

    @Binding var isShowing: Bool
    var content: () -> Content

    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .center) {
                if (!self.isShowing) {
                    self.content()
                }
                if (self.isShowing) {
                    self.content()
                        .disabled(true)
                        .blur(radius: 3)

                    VStack {
                        Text("Modal")
                    }
                    .frame(width: geometry.size.width / 2,
                           height: geometry.size.height / 5)
                    .background(Color.secondary.colorInvert())
                    .foregroundColor(Color.primary)
                    .cornerRadius(20)
                    .transition(.moveAndFade) // associated transition to the modal view
                }
            }
        }
    }

}

Я повторно использовал Transition.moveAndFade из учебника " Анимационные представления и переходы".

Это определяется так:

extension AnyTransition {
    static var moveAndFade: AnyTransition {
        let insertion = AnyTransition.move(edge: .trailing)
            .combined(with: .opacity)
        let removal = AnyTransition.scale()
            .combined(with: .opacity)
        return .asymmetric(insertion: insertion, removal: removal)
    }
}

Вы можете проверить это - в симуляторе, а не в превью - вот так:

struct ContentView: View {

    @State var isShowingModal: Bool = false

    func toggleModal() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            withAnimation {
                self.isShowingModal = true
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                withAnimation {
                    self.isShowingModal = false
                }
            }
        }
    }

    var body: some View {
        ModalView(isShowing: $isShowingModal) {
            NavigationView {
                List(["1", "2", "3", "4", "5"].identified(by: \.self)) { row in
                    Text(row)
                }.navigationBarTitle(Text("A List"), displayMode: .large)
            }.onAppear { self.toggleModal() }
        }
    }

}

Благодаря этому переходу вы увидите, как модал sliding in from the trailing edge, и он будет zoom and fade out when it is dismissed.

Ответ 4

Основная концепция SwiftUI - следить за потоком данных.

Вы должны использовать переменную @State и @State значение этой переменной, чтобы контролировать выталкивание и удаление.

struct MyView: View {
    @State
    var showsUp = false

    var body: some View {
        Button(action: { self.showsUp.toggle() }) {
            Text("Pop")
        }
        .presentation(
            showsUp ? Modal(
                Button(action: { self.showsUp.toggle() }) {
                    Text("Dismiss")
                }
            ) : nil
        )
    }
}

Ответ 5

Я столкнулся с проблемой компиляции при попытке вызвать value для привязки presentationMode. Изменение свойства на wrappedValue исправило проблему для меня. Я предполагаю, что valuewrappedValue - обновление языка. Я думаю, что это примечание было бы более уместным в качестве комментария к ответу Чака Н, но у меня недостаточно точек повторения, чтобы комментировать, я также предложил это изменение как и изменить, но мое изменение было отклонено как более подходящее в качестве комментария или ответа.