@State var 未按预期在 LazyVGrid 中更新
@State var not updated as expected in LazyVGrid
我无法理解为什么我的变量“selectedItem”在此代码的一部分中被更新,而另一部分却没有。我的目标是当您点击网格中的图像时,它将选定的图像名称传递给 ImageDetailView(理想情况下我希望它是一个 Navigationlink,但 sheet 对我来说更容易测试.. 一次一个步骤)。
在我有 print(selectedItem)
的地方,它会按预期在控制台中打印 LazyVGrid 的点击图像的名称。厉害了。
但是打开的 sheet 是空白的,因为它仍在寻找“测试”...控制台显示一条消息说“在资产目录中找不到名为 'test' 的图像... “
为什么sheet还在使用“test”的初始化值?而不是更新值?
构造 ImagesView:视图 {
@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
构造 ImageDetailView: 视图 {
@State var selectedItem: String
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
Image(selectedItem)
.resizable()
.aspectRatio(contentMode: .fit)
.cornerRadius(10)
}
}
}
Sheet 在使用 isPresented
.
加载内容时很挑剔
一个更可靠的解决方案是使用 sheet(item: )
,它只需对 selectedItem 进行少量修改即可适用于您的情况——它必须符合 Identifiable
。所以,你可以这样包装它:
struct ImageSelection : Identifiable {
var name : String
var id: String {
return name
}
}
那么,selectedItem
就会变成一个可选的,因为它会决定sheet是否打开。这是一个最小的示例,显示了可选的以及如何将其与 sheet(item:)
:
一起使用
struct ContentView : View {
@State var selectedItem : ImageSelection?
var body: some View {
Text("Test")
.sheet(item: $selectedItem) { item in
Text(item.name)
}
}
}
(请注意,item
被传递到 sheet 的闭包中——这就是您确保使用正确数据的方式)
更新
根据您的评论:
selectedItem = ImageSelection(name: imageSet[index].name)
print(selectedItem?.name)
我无法理解为什么我的变量“selectedItem”在此代码的一部分中被更新,而另一部分却没有。我的目标是当您点击网格中的图像时,它将选定的图像名称传递给 ImageDetailView(理想情况下我希望它是一个 Navigationlink,但 sheet 对我来说更容易测试.. 一次一个步骤)。
在我有 print(selectedItem)
的地方,它会按预期在控制台中打印 LazyVGrid 的点击图像的名称。厉害了。
但是打开的 sheet 是空白的,因为它仍在寻找“测试”...控制台显示一条消息说“在资产目录中找不到名为 'test' 的图像... “
为什么sheet还在使用“test”的初始化值?而不是更新值?
构造 ImagesView:视图 {
@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
构造 ImageDetailView: 视图 {
@State var selectedItem: String
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
Image(selectedItem)
.resizable()
.aspectRatio(contentMode: .fit)
.cornerRadius(10)
}
}
}
Sheet 在使用 isPresented
.
一个更可靠的解决方案是使用 sheet(item: )
,它只需对 selectedItem 进行少量修改即可适用于您的情况——它必须符合 Identifiable
。所以,你可以这样包装它:
struct ImageSelection : Identifiable {
var name : String
var id: String {
return name
}
}
那么,selectedItem
就会变成一个可选的,因为它会决定sheet是否打开。这是一个最小的示例,显示了可选的以及如何将其与 sheet(item:)
:
struct ContentView : View {
@State var selectedItem : ImageSelection?
var body: some View {
Text("Test")
.sheet(item: $selectedItem) { item in
Text(item.name)
}
}
}
(请注意,item
被传递到 sheet 的闭包中——这就是您确保使用正确数据的方式)
更新 根据您的评论:
selectedItem = ImageSelection(name: imageSet[index].name)
print(selectedItem?.name)