#ios #swift #swiftui
#iOS #swift #swiftui
Вопрос:
Я создаю приложение SwiftUI для iPhone и iPad, которое начинается со списка. Каждая запись представляет другое представление, к которому пользователь может перейти. Для каждого представления может потребоваться объяснение, поэтому я хотел бы показать его при первом переходе пользователя к ним. Я пытаюсь использовать fullScreenCover
, чтобы показать это «вводное представление».
Но когда полноэкранный режим пытается показать, я получаю следующее, и, следовательно, вводный вид никогда не отображается:
2020-10-22 09:55:05.587361-0700 test[81095:3217286] [Presentation] Attempt to present
<_TtGC7SwiftUI22SheetHostingControllerVS_7AnyView_: 0x7f883e51bcc0> on
<_TtGC7SwiftUI41StyleContextSplitViewNavigationControllerVS_14NoStyleContext_: 0x7f883e819a00>
(from <_TtGC7SwiftUIP13$7fff562fec9428DestinationHostingControllerVS_7AnyView_: 0x7f883e4169b0>)
whose view is not in the window hierarchy.
Я понимаю, что ошибка заключается в том, что я пытаюсь представить представление поверх другого, которого еще нет в иерархии представлений окна. Я сталкивался с другими вопросами, которые задают похожие вопросы, и решение состояло в том, чтобы подождать, пока вы не получите уведомление о том, что представление отображается на экране (через viewDidAppear
и тому подобное). Но у меня есть некоторые наблюдения, которые заставляют меня думать, что это другой случай:
-
Ошибка возникает только тогда, когда
NavigationLink
переход к подробному представлению находится внутри aList
(см. Код ниже). Когда вне aList
все работает нормально. -
Ошибка также возникает только на iPhone. На целевом устройстве iPhone я получаю сообщение об ошибке, когда объект
NavigationLink
находится внутри aList
, но все работает, когда это не так. На цели iPad конечнаяfullScreenCover
работа работает независимо от того, была лиNavigationLink
она внутри aList
или нет.- До сих пор вся моя работа была в симуляторе, если это имеет значение.
Ниже приведен код, который воспроизводит проблему. Обратите внимание на закомментированный List
контейнер MainAppView
. Если я запускаю его как есть на iPhone, вид ввода отображается. Если я раскомментирую List
контейнер, я получу сообщение об ошибке. Я понимаю, что мне чего-то не хватает в том, как изменяется иерархия представлений при использовании a List
, и это как-то отличается, когда вы находитесь в разных классах размеров. Но я не совсем понимаю, что это такое или где об этом узнать. Любая помощь будет с благодарностью принята.
import SwiftUI
struct MainAppView: View {
var body: some View {
NavigationView {
// List { // <-- Uncomment this line (and closing brace 3 lines down) to hit issue
NavigationLink(destination: ComplicatedView()) {
Text("Go to complicated view")
}
// }
}
}
}
struct ComplicatedView: View {
@State private var showingCover = true
var body: some View {
DetailsOfComplicatedView()
.fullScreenCover(isPresented: $showingCover, content: {
TutorialView()
})
}
}
struct DetailsOfComplicatedView: View {
var body: some View {
VStack {
Text("Some nitty gritty details go here.")
Text("But if it all goes right, it should immediately get covered up by a tutorial view. Does it?")
}
}
}
struct TutorialView: View {
var body: some View {
VStack {
Text("I'd like to take a moment and explain this complicated view.")
Button("OK") {
// Do something to dismiss. But not relevant to the question.
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MainAppView()
}
}
Ответ №1:
Немного рано, появилась активация полноэкранного режима при просмотре, как показано ниже (протестировано с Xcode 12 / iOS 14)
struct ComplicatedView: View {
@State private var showingCover = false
var body: some View {
DetailsOfComplicatedView()
.fullScreenCover(isPresented: $showingCover, content: {
TutorialView()
})
.onAppear { self.showingCover = true }
}
}
Комментарии:
1. Спасибо Asperi; это действительно работает. Мне любопытно, почему исходный код (т. Е. Без
onAppear
) Не будет работать на iPhone, когда он находится внутри списка? Каждый примерfullScreenCover
, который я видел, заставляет думать, что так и должно быть. Это просто новый API, который не работает?