如何在 SwiftUI 中再次初始化 View?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中再次初始化 View?【英文标题】:How can I initialize View Again in SwiftUI? 【发布时间】:2020-07-29 00:22:30 【问题描述】:我在我的项目中使用 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 中的一个单元格来查看详细信息。然后我用返回按钮回来。我再次单击单元格以转到详细信息,但未打开新视图。它显示了旧视图。
在我忘记之前,我的 Builder 类是:
final class DetailViewBuilder
static func make(object: Something) -> DetailView
let viewModel = DetailViewModel(object: object)
let view = DetailView(viewModel: viewModel)
return view
注意:如果我将使用 Sheet Presented,它就可以工作。它正在创建新视图。但我想使用 NavigationLink。谢谢。
【问题讨论】:
【参考方案1】:您只需要在构建器中延迟创建目标,@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))
【讨论】:
谢谢。它正在工作。真的@ViewBuilder 是一个很好的解决方案。 这是一个很好的答案!当我的当前视图被多次刷新时,它也解决了我多次创建目标视图的问题【参考方案2】:SwiftUI 会急切地初始化NavigationView
链接,因此您不能每次都依赖它们的初始化程序来运行。如果为 DetailView 编写自定义 init()
init(viewModel: DetailViewModel)
self.viewModel = viewModel
print("Initialising \(self)")
当您的 FirstView 加载时,您会看到每个导航链接的行打印出来。
根据您想要做什么,您可以在 DetailView 上实现 .onAppear
闭包,这将在视图出现时更改数据。尝试提供实现示例有点棘手,因为我不确定您在这里的具体目标是什么。
对此有一些有趣的讨论: https://www.notion.so/Lazy-Loading-Data-with-SwiftUI-and-Combine-70546ec6aca3481f80d104cd1f10a31a
这里的任何建议看起来是否与您正在尝试做的事情相关?
【讨论】:
以上是关于如何在 SwiftUI 中再次初始化 View?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中创建一个获取 View 并返回自定义结果的函数?
如何创建一个带有可选辅助 View 参数的 SwiftUI 视图?
SwiftUI 如何快速识别视图(View)界面的刷新是由哪个状态的改变导致的?