Работают ли onAppear и onDisappear в NavigationView приложения SwiftUI должным образом?
Я хотел бы знать, является ли поведение onAppear и Disappear в SwiftUI (Xcode 11 beta 6, как я пишу это) тем, что разработчик посчитал бы более полезным, или это скорее проблема, чем функция.
Прямо сейчас, если мы используем каскадную навигацию, как вы найдете в примере кода, который я присоединяю (который компилируется и работает нормально в Xcode 11b6), консольный вывод пользователя, перемещающегося вперед и назад, просто вызовет onAppear только в случае новый вид нагрузки в прямом направлении (имеется в виду углубление).
В навигации: Root -> NestedView1 -> NestedView2 -> NestedView3, при добавлении помощника отладки на каждом этапе просмотра,
.onAppear(perform: {print("onAppear level N")})
.onDisappear(perform: {print("onDisappear level N")})
консоль отладки покажет
onAppear root level 0
onAppear level 1
onAppear level 2
onAppear level 3
(Нет при исчезновении запуска)
но возвращаясь Root <- NestedView1 <- NestedView2 <- NestedView3
консоль отладки покажет... ничего
(Нет при запуске или при исчезновении)
struct NestedViewLevel3: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
Text("Level 3")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 3", displayMode: .inline)
.onAppear(perform: {print("onAppear level 3")})
.onDisappear(perform: {print("onDisappear level 3")})
}
}
struct NestedViewLevel2: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel3()) {
Text("To level 3")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 2")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 2", displayMode: .inline)
.onAppear(perform: {print("onAppear level 2")})
.onDisappear(perform: {print("onDisappear level 2")})
}
}
struct NestedViewLevel1: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel2()) {
Text("To level 2")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 1")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 1", displayMode: .inline)
.onAppear(perform: {print("onAppear level 1")})
.onDisappear(perform: {print("onDisappear level 1")})
}
}
struct RootViewLevel0: View {
var body: some View {
NavigationView {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel1()) {
Text("To level 1")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
}
}
.navigationBarTitle("Root level 0", displayMode: .inline)
.navigationBarBackButtonHidden(false)
.navigationViewStyle(StackNavigationViewStyle())
.onAppear(perform: {print("onAppear root level 0")})
.onDisappear(perform: {print("onDisappear root level 0")})
}
}
struct ContentView: View {
var body: some View {
RootViewLevel0()
}
}
}
Теперь разработчик должен иметь onAppear и onDisappear:
1) Запускается с целью запуска действий, которые необходимо выполнить только один раз и только тогда, когда пользователь движется вперед, как в текущем наблюдаемом поведении.
2) Срабатывает каждый раз, когда появляется представление, более похожее на название действия, будь то в обратном направлении, вперед и любое количество раз.
?
Я бы выбрал вариант 2, простой и жестокий (и то, что мне сейчас нужно), но я довольно наивный новичок в NavigationView, и вариант 2 может нарушить многие устоявшиеся парадигмы, которые я не принимаю во внимание.
Ваш отзыв поможет мне выяснить, обоснованно ли соответствующее дело Помощника по обратной связи для SwiftUI.
1 ответ
Это была ошибка на стороне Apple.
.onAppear () теперь работает как положено в iOS 13.1 и XCode 11 Beta 7.
При навигации вперед и назад к NavigationView, .onAppear() сработает.
Начиная с бета-версии XCode 11.2 (выпущенной 10 февраля 2019 г.), оба метода (включая.onDisappear()) запускаются правильно.
Обратите внимание, что .onDisappear()
не запускался до этой бета-версии.
Обе команды: .onDisappear(выполнить:) и.onAppear(выполнить:)
ошибка функции NavigationView (.navigationBarTitle):
.navigationBarTitle("Opciones", displayMode: .inline)
При использовании navigationBarTitle удаляется или не работает в представлении, в котором вы его используете. Это происходит с использованием ОБА: .onDisappear(выполнить:) .onAppear(выполнить:)
Использование Xcode версии 12.2 (12B45b)