ios - PresentationLink 始终使用相同的目标对象
问题描述
令我惊讶的是,每当我点击 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")
}
}
在这种情况下,这将是从 NavigationLink推送的PresenterExample
礼物。从那里,假设用户向下滑动并因此关闭演示文稿。当它重新点击in时,它会重新打开,这不是我想要的。我想再次显示。StackFirstView
StackSecondView
PresentationLink
PresenterExample
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
bypresentationCount
。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
down 传递给StackFirstView
然后将.id(presentationCount)
修饰符应用于NavigationView
's 的内容。如果模态在显示时被解除并再次呈现,这会使操场崩溃StackSecondView
。我提交了 FB6687850。
更新
Ryan Ashcraft 的这条推文向我展示了一种解决方法,可以让第二次尝试生效。它将 ' 的内容包装Modal
在 aGroup
中,并将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
whenpresentationCount
是奇数。
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
vs. ZStack<StackFirstView>
),这足以说服它这些是不相关的视图,因此它会丢弃先前呈现的视图而不是重用它。
推荐阅读
- java - PDFBox 不支持多种语言
- python - 在 hangman 中替换部分字符串时遇到问题
- sql - 用 MS Access 中另一个字段的值填充一个字段
- python - 删除未知的特殊字符
- python - Scrapy:已抓取但未抓取任何数据
- perl - 从 perl 中的二维数组中删除重复项
- asp.net-core - HTTP 错误 500.30 - ASP.NET Core 2.2 中的 ANCM 进程内启动失败错误
- php - if-else 语句面临问题。它总是重定向到第一个条件
- tfs - Team Foundation Server 2015 到 2018 升级错误(步骤 909)
- mule - 无法传递标头