SwiftUI отклонить модал - PullRequest
15 голосов
/ 09 июня 2019

Поскольку SwiftUI является декларативным, метод dismiss отсутствует. Как можно добавить кнопку отклонения / закрытия к DetailView?

struct DetailView: View {
  var body: some View {
  Text("Detail")
  }
}

struct ContentView : View {
  var body: some View {
  PresentationButton(Text("Click to show"), destination: DetailView())
  }
}

Ответы [ 4 ]

18 голосов
/ 12 июня 2019

Другим способом отклонения модального режима является использование isPresented переменной окружения, которая:

Привязка к логическому значению, которое указывает, является ли этот экземпляр часть представленной в настоящее время иерархии.

Все, что вам нужно сделать, это установить значение этой переменной равным false в вашем модальном представлении:

struct DetailView : View {

  @Environment(\.isPresented) var isPresented: Binding<Bool>?

  var body: some View {
    Group {
      Text("Detail view")
      Button(action: {
        self.isPresented?.value = false
      }) {
        Text("Dismiss")
      }
    }
  }
}

struct ContentView : View {
  var body: some View {
   // PresentationButton(Text("Show modal"), destination: DetailView())
   // In Xcode 11 beta 3, 'PresentationButton' is deprecated and renamed to 'PresentationLink'
    PresentationLink(destination: DetailView()) {
      Text("Show modal")
    }
  }
}

enter image description here

12 голосов
/ 10 июня 2019

Вот способ отклонить представленное представление.

struct DetailView: View {
    @Binding
    var dismissFlag: Bool

    var body: some View {
        Group {
            Text("Detail")
            Button(action: {
                self.dismissFlag.toggle()
            }) {
                Text("Dismiss")
            }
        }

    }
}

struct ContentView : View {
    @State var dismissFlag = false

    var body: some View {
        Button(action: {
            self.dismissFlag.toggle()
        })
        { Text("Show") }
            .presentation(!dismissFlag ? nil :
                Modal(DetailView(dismissFlag: $dismissFlag)) {
                print("dismissed")
            })
    }
}

enter image description here

6 голосов
/ 12 июня 2019

Вы можете реализовать это.

struct view: View {
    @Environment(\.isPresented) private var isPresented

    private func dismiss() {
        isPresented?.value = false
    }
}
2 голосов
/ 11 июня 2019

Поскольку PresentationButton прост в использовании, но скрытие состояния, которое подрывает предсказательный характер SwiftUI, я реализовал его с помощью доступного Binding.

public struct BindedPresentationButton<Label, Destination>: View where Label: View, Destination: View {
    /// The state of the modal presentation, either `visibile` or `off`.
    private var showModal: Binding<Bool>

    /// A `View` to use as the label of the button.
    public var label: Label

    /// A `View` to present.
    public var destination: Destination

    /// A closure to be invoked when the button is tapped.
    public var onTrigger: (() -> Void)?

    public init(
        showModal: Binding<Bool>,
        label: Label,
        destination: Destination,
        onTrigger: (() -> Void)? = nil
    ) {
        self.showModal = showModal
        self.label = label
        self.destination = destination
        self.onTrigger = onTrigger
    }

    public var body: some View {
        Button(action: toggleModal) {
            label
        }
        .presentation(
            !showModal.value ? nil :
                Modal(
                    destination, onDismiss: {
                        self.toggleModal()
                    }
                )
        )
    }

    private func toggleModal() {
        showModal.value.toggle()
        onTrigger?()
    }
}

Вот как это используется:

struct DetailView: View {
    @Binding var showModal: Bool

    var body: some View {
        Group {
            Text("Detail")
            Button(action: {
                self.showModal = false
            }) {
                Text("Dismiss")
            }
        }
    }
}

struct ContentView: View {
    @State var showModal = false

    var body: some View {
        BindedPresentationButton(
            showModal: $showModal,
            label: Text("Show"),
            destination: DetailView(showModal: $showModal)
        ) {
            print("dismissed")
        }
    }
}
...