令我惊讶的是,每当我点击 PresentationLink 中嵌入的按钮时,相同的 View 引用始终会出现。我的意思是我们不创建 View 的另一个实例。 这是有道理的,因为目标对象是在 body 属性中创建的,因此除非发生更改,否则不会重新创建。
你们知道我们是否有一种简单的方法可以在每次按下按钮时重新创建一个新 View 吗?还是设计使然,应该这样使用?
谢谢!
编辑
在@dfd 的评论之后,它似乎是设计好的。 现在如何处理这个用例:
Let's say I present a NavigationView and I pushed one view. If I dismiss and re present, I will go back on the view I previously pushed. In this case, I believe it's wrong as I'd like the user to go through the complete flow every single time. How can I make sure that I go back on the first screen everytime?
谢谢你(再次)!
编辑 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
。
从那里,假设用户向下滑动并因此关闭了演示文稿。当它点击返回 PresenterExample
中的 PresentationLink
时,它将在 StackSecondView
上重新打开,这不是我想要的。我想再次显示 StackFirstView
。
更有意义? :)
最佳答案
第一次尝试:失败
我尝试使用 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
使用不同的标识符是完全不同的 View 。我已经成功地将其用于动画过渡。它应该增加
presentationCount
当StackFirstView
被解雇,以便下一个StackFirstView
获取不同的标识符。
问题是 SwiftUI 从不调用 onDisappear
关闭当前 View 或其任何 subview 。我很确定这是一个 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
的第二次及以后的演讲只是呈现一个空白 View 。同样,我很确定这是一个 SwiftUI 错误。我提交了 FB6687804。
我尝试通过 presentationCount
下降到 StackFirstView
然后应用 .id(presentationCount)
NavigationView
的修饰符的内容。如果模态在显示 StackSecondView
时被关闭并再次显示, Playground 就会崩溃.我提交了 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
的状态在每个演示文稿上。请注意 id
必须应用于 Group
的内容,而不是 Group
本身,以解决 SwiftUI 错误。
第三次尝试:成功
我修改了第二次尝试,而不是使用 id
修饰符,它包装了 StackFirstView
在 ZStack
里面什么时候presentationCount
是奇数。
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())
这行得通。我想 SwiftUI 看到模态的内容每次都是不同的类型( StackFirstView
与 ZStack<StackFirstView>
)并且这足以说服它这些是不相关的 View ,因此它丢弃了先前呈现的 View 而不是重新使用它。
关于ios - PresentationLink 始终使用相同的目标对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57046623/