令我感到惊讶的是,每当我点击PresentationLink中嵌入的按钮时,始终会出现相同的视图引用。我的意思是我们不创建视图的另一个实例。 这是有道理的,因为目标对象是在body属性内创建的,因此除非发生更改,否则不会重新创建。
你们知道我们每次点击按钮时是否都有一种简单的方法来重新创建新视图?还是设计使然,应该像这样使用?
谢谢!
编辑
@dfd发表评论后,这似乎是设计使然。 现在如何处理该用例:
假设我展示了一个NavigationView,然后按下了一个视图。如果我 撤消并发表讲话,我将回到以前的观点 推。在这种情况下,我认为这是错误的,因为我希望用户离开 每遍一次完整的流程。我如何确保 我每次都回到第一个屏幕吗?
再次感谢您!
编辑2
以下是一些代码:
struct PresenterExample : View {
var body: some View {
VStack {
PresentationLink(destination: CandidateCreateProfileJobView()) {
Text("Present")
}
}
}
}
struct StackFirstView : View {
var body: some View {
NavigationLink(destination: StackSecondView()) {
Text("Got to view 2")
}
}
}
struct StackSecondView : View {
var body: some View {
Text("View 2")
}
}
在这种情况下,将PresenterExample
出现StackFirstView
,它将从NavigationLink中推送StackSecondView
。
假设用户从那里向下滑动,因此关闭了演示文稿。在PresentationLink
中的PresenterExample
上单击时,它将在StackSecondView
上重新打开,这不是我想要的。我想再次显示StackFirstView
。
更有意义吗? :)
答案 0 :(得分:1)
我尝试使用id
修饰符告诉SwiftUI将StackFirstView
的每次显示都视为与以前的视图无关的全新视图:
import SwiftUI
struct PresenterExample : View {
var body: some View {
VStack {
PresentationLink("Present", destination:
StackFirstView()
.onDisappear {
print("onDisappear")
self.presentationCount += 1
}
)
}
}
@State private var presentationCount = 0
}
struct StackFirstView : View {
var body: some View {
NavigationView {
NavigationLink(destination: StackSecondView()) {
Text("Go to view 2")
}.navigationBarTitle("StackFirstView")
}
}
}
struct StackSecondView : View {
var body: some View {
Text("View 2")
.navigationBarTitle("StackSecondView")
}
}
import PlaygroundSupport
PlaygroundPage.current.liveView = UIHostingController(rootView: PresenterExample())
此应执行以下操作:
它应通过StackFirstView
来标识presentationCount
。 SwiftUI应该将具有不同标识符的每个StackFirstView
视为完全不同的视图。我已经成功地将其用于动画过渡。
当取消presentationCount
时,它应递增StackFirstView
,以便下一个StackFirstView
获得不同的标识符。
问题在于,SwiftUI永远不会为呈现的视图或其任何子视图调用onDisappear
闭包。我很确定这是一个SwiftUI错误(从Xcode 11 beta 3开始)。我提交了FB6687752。
接下来,我尝试使用presentation(Modal?)
修饰符自己管理演示文稿,因此不需要onDisappear
修饰符:
import SwiftUI
struct PresenterExample : View {
var body: some View {
VStack {
Button("Present") {
self.presentModal()
}.presentation(modal)
}
}
@State private var shouldPresent = false
@State private var presentationCount = 0
private func presentModal() {
presentationCount += 1
shouldPresent = true
}
private var modal: Modal? {
guard shouldPresent else { return nil }
return Modal(StackFirstView().id(presentationCount), onDismiss: { self.shouldPresent = false })
}
}
struct StackFirstView : View {
var body: some View {
NavigationView {
NavigationLink(destination: StackSecondView()) {
Text("Go to view 2")
}.navigationBarTitle("StackFirstView")
}
}
}
struct StackSecondView : View {
var body: some View {
Text("View 2")
}
}
import PlaygroundSupport
PlaygroundPage.current.liveView = UIHostingController(rootView: PresenterExample())
这以另一种方式失败。 StackFirstView
的第二次和以后的演示仅显示空白视图。再次,我很确定这是一个SwiftUI错误。我提交了FB6687804。
我尝试将presentationCount
向下传递到StackFirstView
,然后将.id(presentationCount)
修饰符应用于NavigationView
的内容。如果在显示StackSecondView
时取消模态并再次显示模态,则会使运动场崩溃。我提交了FB6687850。
This tweet from Ryan Ashcraft向我展示了一种解决方法,可以使第二次尝试有效。它将Modal
的内容包装在Group
中,并将id
修饰符应用于Group
的内容:
import SwiftUI
struct PresenterExample : View {
var body: some View {
VStack {
Button("Present") {
self.presentModal()
}.presentation(modal)
}
}
@State private var shouldPresent = false
@State private var presentationCount = 0
private func presentModal() {
presentationCount += 1
shouldPresent = true
}
private var modal: Modal? {
guard shouldPresent else { return nil }
return Modal(Group { StackFirstView().id(presentationCount) }, onDismiss: { self.shouldPresent = false })
}
}
struct StackFirstView : View {
var body: some View {
NavigationView {
NavigationLink(destination: StackSecondView()) {
Text("Go to view 2")
}.navigationBarTitle("StackFirstView")
}
}
}
struct StackSecondView : View {
var body: some View {
Text("View 2")
}
}
import PlaygroundSupport
PlaygroundPage.current.liveView = UIHostingController(rootView: PresenterExample())
此修订后的第二次尝试成功重置了每个演示文稿上Modal
的状态。请注意,{@ {1}}必须应用于id
的内容,而不是Group
本身,才能解决SwiftUI错误。
我修改了第二种尝试,以便当Group
为奇数时,它不使用id
修饰符,而是将StackFirstView
包装在ZStack
内。
presentationCount
这有效。我想SwiftUI会看到模态的内容每次都是不同的类型(import SwiftUI
struct PresenterExample : View {
var body: some View {
VStack {
Button("Present") {
self.presentModal()
}.presentation(modal)
}
}
@State private var shouldPresent = false
@State private var presentationCount = 0
private func presentModal() {
presentationCount += 1
shouldPresent = true
}
private var modal: Modal? {
guard shouldPresent else { return nil }
if presentationCount.isMultiple(of: 2) {
return Modal(presentationContent, onDismiss: { self.shouldPresent = false })
} else {
return Modal(ZStack { presentationContent }, onDismiss: { self.shouldPresent = false })
}
}
private var presentationContent: some View {
StackFirstView()
}
}
struct StackFirstView : View {
var body: some View {
NavigationView {
NavigationLink(destination: StackSecondView()) {
Text("Go to view 2")
}.navigationBarTitle("StackFirstView")
}
}
}
struct StackSecondView : View {
var body: some View {
Text("View 2")
}
}
import PlaygroundSupport
PlaygroundPage.current.liveView = UIHostingController(rootView: PresenterExample())
与StackFirstView
),足以说服它们是不相关的视图,因此它代替了先前提供的视图重用它。