如何在 SwiftUI 中再次初始化 View?
How can I initialize View Again in SwiftUI?
我在项目中使用 SwfitUI,并且有一个 NavigationView 和 List。我在打开详细视图并单击导航后退按钮后单击单元格。单击导航后退按钮后,我想删除视图(它是 SwiftUI 中的结构)。因为如果我再次单击同一个单元格或按钮,它不会初始化新视图,而是显示旧视图。我想刷新这个视图。我该怎么办?
我的 FirstView 结构是:
struct FirstView: View {
@ObservedObject var viewModel: FirstViewModel
var body: some View {
List(self.viewModel.objects, id: \.id) { object in
ZStack {
DetailViewCell(object: object)
NavigationLink(destination: DetailViewBuilder.make(object)) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
}
我的 DetailView 结构是:
struct DetailView: View {
@ObservedObject var viewModel: DetailViewModel
var body: some View {
ZStack(alignment: .top) {
Color.mainBackground.edgesIgnoringSafeArea(.all)
VStack {
ZStack {
Image("Square")
Image(self.viewModel.currentImage)
}
Text(self.viewModel.currentText)
.padding()
.frame(alignment: .center)
.minimumScaleFactor(0.1)
Spacer()
Button(action: {
self.viewModel.pressedPlayOrPauseButton()
}, label: {
Image(self.viewModel.isPlaying ? "Pause" : "Play").foregroundColor(Color("Orange"))
}).padding()
}
}
}
}
首先,我通过单击 FirstView 中的一个单元格转到详细信息。然后我用后退按钮回来。我再次单击一个单元格以转到详细信息,但没有打开新视图。它显示旧视图。
在我忘记之前,我的生成器 Class 是:
final class DetailViewBuilder {
static func make(object: Something) -> DetailView {
let viewModel = DetailViewModel(object: object)
let view = DetailView(viewModel: viewModel)
return view
}
}
注意:如果我将使用 Sheet 呈现,它会起作用。它正在创建新视图。但我想使用 NavigationLink。谢谢。
SwiftUI 急切地初始化 NavigationView
links,所以你不能每次都依赖他们的初始化程序来 运行。如果您为 DetailView
编写自定义 init()
init(viewModel: DetailViewModel) {
self.viewModel = viewModel
print("Initialising \(self)")
}
当您的 FirstView 加载时,您会看到每个导航都打印出该行 link。
根据您想要执行的操作,您可以在 DetailView 上实施 .onAppear {}
闭包,这将在视图出现时更改数据。尝试提供实施示例有点棘手,因为我不确定您的具体目标是什么。
在以下位置对此进行了一些有趣的讨论:
https://www.notion.so/Lazy-Loading-Data-with-SwiftUI-and-Combine-70546ec6aca3481f80d104cd1f10a31a
这里的任何建议看起来是否与您正在尝试做的事情相关?
您只需要在构建器中推迟目标创建,@ViewBuilder
是一个很好的工具。
仅在 body
呈现时(即在您的情况下明确单击导航时),才可以使用以下包装器创建真正的目的地
测试 Xcode 11.4 / iOS 13.4
struct DeferView<Content: View>: View {
let content: () -> Content
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content() // << everything is created here
}
}
现在是你的建造者
final class DetailViewBuilder {
static func make(object: Something) -> some View {
DeferView {
DetailView(viewModel: DetailViewModel(object: object))
}
}
}
我在项目中使用 SwfitUI,并且有一个 NavigationView 和 List。我在打开详细视图并单击导航后退按钮后单击单元格。单击导航后退按钮后,我想删除视图(它是 SwiftUI 中的结构)。因为如果我再次单击同一个单元格或按钮,它不会初始化新视图,而是显示旧视图。我想刷新这个视图。我该怎么办?
我的 FirstView 结构是:
struct FirstView: View {
@ObservedObject var viewModel: FirstViewModel
var body: some View {
List(self.viewModel.objects, id: \.id) { object in
ZStack {
DetailViewCell(object: object)
NavigationLink(destination: DetailViewBuilder.make(object)) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
}
我的 DetailView 结构是:
struct DetailView: View {
@ObservedObject var viewModel: DetailViewModel
var body: some View {
ZStack(alignment: .top) {
Color.mainBackground.edgesIgnoringSafeArea(.all)
VStack {
ZStack {
Image("Square")
Image(self.viewModel.currentImage)
}
Text(self.viewModel.currentText)
.padding()
.frame(alignment: .center)
.minimumScaleFactor(0.1)
Spacer()
Button(action: {
self.viewModel.pressedPlayOrPauseButton()
}, label: {
Image(self.viewModel.isPlaying ? "Pause" : "Play").foregroundColor(Color("Orange"))
}).padding()
}
}
}
}
首先,我通过单击 FirstView 中的一个单元格转到详细信息。然后我用后退按钮回来。我再次单击一个单元格以转到详细信息,但没有打开新视图。它显示旧视图。
在我忘记之前,我的生成器 Class 是:
final class DetailViewBuilder {
static func make(object: Something) -> DetailView {
let viewModel = DetailViewModel(object: object)
let view = DetailView(viewModel: viewModel)
return view
}
}
注意:如果我将使用 Sheet 呈现,它会起作用。它正在创建新视图。但我想使用 NavigationLink。谢谢。
SwiftUI 急切地初始化 NavigationView
links,所以你不能每次都依赖他们的初始化程序来 运行。如果您为 DetailView
init(viewModel: DetailViewModel) {
self.viewModel = viewModel
print("Initialising \(self)")
}
当您的 FirstView 加载时,您会看到每个导航都打印出该行 link。
根据您想要执行的操作,您可以在 DetailView 上实施 .onAppear {}
闭包,这将在视图出现时更改数据。尝试提供实施示例有点棘手,因为我不确定您的具体目标是什么。
在以下位置对此进行了一些有趣的讨论: https://www.notion.so/Lazy-Loading-Data-with-SwiftUI-and-Combine-70546ec6aca3481f80d104cd1f10a31a
这里的任何建议看起来是否与您正在尝试做的事情相关?
您只需要在构建器中推迟目标创建,@ViewBuilder
是一个很好的工具。
仅在 body
呈现时(即在您的情况下明确单击导航时),才可以使用以下包装器创建真正的目的地
测试 Xcode 11.4 / iOS 13.4
struct DeferView<Content: View>: View {
let content: () -> Content
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content() // << everything is created here
}
}
现在是你的建造者
final class DetailViewBuilder {
static func make(object: Something) -> some View {
DeferView {
DetailView(viewModel: DetailViewModel(object: object))
}
}
}