@State var 在 LazyVGrid 中未按预期更新

Posted

技术标签:

【中文标题】@State var 在 LazyVGrid 中未按预期更新【英文标题】:@State var not updated as expected in LazyVGrid 【发布时间】:2021-02-13 21:26:43 【问题描述】:

我无法理解为什么我的变量“selectedItem”在这段代码的一部分中被更新,而不是另一部分。我的目标是做到这一点,因此当您点击网格中的图像时,它将所选图像名称传递给 ImageDetailView(理想情况下,我希望它是 Navigationlink,但工作表对我来说更容易测试..一个一步一步)。

在我有print(selectedItem) 的地方,它会按预期在控制台中打印 LazyVGrid 的点击图像的名称。太棒了。

但随后打开的工作表是空白的,因为它仍在寻找“测试”...控制台显示一条消息“在资产目录中找不到名为 'test' 的图像...”

为什么工作表仍然使用“test”的初始化值?而不是更新后的值?

结构图像视图:查看

@State var gridLayout: [GridItem] = [ GridItem() ]
var title: String
var imageSet = [Photo]()
@State private var selectedItem = "test"

var body: some View 
    ZStack 
        Color.black.edgesIgnoringSafeArea(.all)
        GeometryReader   reader in
            ScrollView 
                LazyVGrid(columns: gridLayout, alignment: .center, spacing: 10) 
                    ForEach(imageSet.indices)  index in
                        Image(imageSet[index].name)
                            .resizable()
                            .onTapGesture 
                                showImageDetailView = true
                                selectedItem = imageSet[index].name
                                print(selectedItem)                                  
                                                          
                            )
                        .padding(.horizontal, 10)
                        .padding(.bottom, 25)
                    
                
                .sheet(isPresented: $showImageDetailView, content: 
                    ImageDetailView(selectedItem: selectedItem)
                )

这是 ImageDetailView

struct ImageDetailView: 查看

@State var selectedItem: String

var body: some View 
    
    ZStack 
        Color.black.edgesIgnoringSafeArea(.all)
       Image(selectedItem)

            .resizable()
            .aspectRatio(contentMode: .fit)
            .cornerRadius(10)
    
    

【问题讨论】:

【参考方案1】:

Sheet 对何时使用 isPresented 加载其内容很挑剔。

更可靠的解决方案是使用sheet(item: ),只需对 selectedItem 稍作修改即可适应您的情况——它必须符合Identifiable。所以,你可以像这样包装它:

struct ImageSelection : Identifiable 
        var name : String
        var id: String 
            return name
        
    

然后,selectedItem 将成为可选项,因为它将确定工作表是否打开。这是一个最小的示例,展示了可选项以及如何将其与 sheet(item:) 一起使用:

struct ContentView : View 
    @State var selectedItem : ImageSelection?
    
    var body: some View 
        Text("Test")
            .sheet(item: $selectedItem)  item in
                Text(item.name)
            
    

(注意item 被传递到工作表的闭包中——这就是您确保使用正确数据的方式)

更新 根据您的 cmets:

selectedItem = ImageSelection(name: imageSet[index].name)
print(selectedItem?.name)

【讨论】:

感谢您的回复!不过,我正在努力实施您的建议。我已经将 selectedItem 与您的示例一样符合 Identifiable ,但即使在尝试工作表(item :) 之前,我也在打印“nil”而不是像之前一样的图像名称 .onTapGesture showImageDetailView = true selectedItem?.name = imageSet[ index].name print(selectedItem?.name) 是的,我明白为什么这不起作用——您必须先设置可选项,然后才能开始设置它的子属性。请参阅我的更新答案。而且,请记住,一旦你实现了 `sheet(item:),你将完全摆脱 showImageDetailView 最终我希望这个 ImageDetailView 从 NavigationLink 实际打开,我只是认为最初使用工作表会更容易,但也许不是!编辑:刚看到你的回复,我会测试一下谢谢!

以上是关于@State var 在 LazyVGrid 中未按预期更新的主要内容,如果未能解决你的问题,请参考以下文章

this.state.articles 在 React js 中未定义

reducer.state.props 在嵌套动作 react/redux 中未定义

已发布/观察到的 var 在视图 swiftui 中未更新,带有调用函数

swiftui+combine:为啥滚动 LazyVGrid 时 isFavoriteO 改变了?

LazyVGrid 中的 NavigationLink 循环返回所有条目,SwiftUI

SwiftUI - 使用可扩展视图构建 LazyVGrid