Отключить родительский модал в SwiftUI из NavigationView - PullRequest
2 голосов
/ 20 января 2020

Мне известно о том, как отклонить модальное изображение из дочернего представления, используя @Environment (\.presentationMode) var presentationMode / self.presentationMode.wrappedValue.dismiss(), но это другая проблема.

Когда вы представляете многостраничный NavigationView в модальном окне и имеете при навигации по нескольким страницам ссылка на presentationMode меняется на NavigationView, поэтому при использовании self.presentationMode.wrappedValue.dismiss() просто появляется последний NavigationView, а не отбрасывается содержащий модал.

Возможно ли это - и если да, то как - отклонить содержащий модал со страницы в дереве NavigationView?

Вот простой пример, показывающий проблему. Если вы создаете проект приложения Xcode Single View с использованием SwiftUI и заменяете код по умолчанию ContentView этим, он должен работать без дальнейших изменений.

import SwiftUI

struct ContentView: View {
  @State var showModal: Bool = false

  var body: some View {
    Button(action: {
      self.showModal.toggle()
    }) {
      Text("Launch Modal")
    }
    .sheet(isPresented: self.$showModal, onDismiss: {
      self.showModal = false
    }) {
      PageOneContent()
    }
  }
}

struct PageOneContent: View {
  var body: some View {
    NavigationView {
      VStack {
        Text("I am Page One")
      }
      .navigationBarTitle("Page One")
      .navigationBarItems(
        trailing: NavigationLink(destination: PageTwoContent()) {
          Text("Next")
        })
      }
  }
}

struct PageTwoContent: View {

  @Environment (\.presentationMode) var presentationMode

  var body: some View {
    NavigationView {
      VStack {
        Text("This should dismiss the modal. But it just pops the NavigationView")
          .padding()

        Button(action: {
          // How to dismiss parent modal here instead
          self.presentationMode.wrappedValue.dismiss()
        }) {
          Text("Finish")
        }
        .padding()
        .foregroundColor(.white)
        .background(Color.blue)
      }
      .navigationBarTitle("Page Two")
    }
  }
}

1 Ответ

2 голосов
/ 20 января 2020

Здесь возможен подход, основанный на использовании собственного явно созданного ключа среды (на самом деле я чувствую, что не правильно использовать presentationMode для этого варианта использования .. в любом случае).

Предложенный подход является общим c и работает из любого представления в иерархии модальных представлений. Протестировано и работает с Xcode 11.2 / iOS 13.2.

// define env key to store our modal mode values
struct ModalModeKey: EnvironmentKey {
    static let defaultValue = Binding<Bool>.constant(false) // < required
}

// define modalMode value
extension EnvironmentValues {
    var modalMode: Binding<Bool> {
        get {
            return self[ModalModeKey.self]
        }
        set {
            self[ModalModeKey.self] = newValue
        }
    }
}


struct ParentModalTest: View {
  @State var showModal: Bool = false

  var body: some View {
    Button(action: {
      self.showModal.toggle()
    }) {
      Text("Launch Modal")
    }
    .sheet(isPresented: self.$showModal, onDismiss: {
    }) {
      PageOneContent()
        .environment(\.modalMode, self.$showModal) // < bind modalMode
    }
  }
}

struct PageOneContent: View {
  var body: some View {
    NavigationView {
      VStack {
        Text("I am Page One")
      }
      .navigationBarTitle("Page One")
      .navigationBarItems(
        trailing: NavigationLink(destination: PageTwoContent()) {
          Text("Next")
        })
      }
  }
}

struct PageTwoContent: View {

  @Environment (\.modalMode) var modalMode // << extract modalMode

  var body: some View {
    NavigationView {
      VStack {
        Text("This should dismiss the modal. But it just pops the NavigationView")
          .padding()

        Button(action: {
          self.modalMode.wrappedValue = false // << close modal
        }) {
          Text("Finish")
        }
        .padding()
        .foregroundColor(.white)
        .background(Color.blue)
      }
      .navigationBarTitle("Page Two")
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...