*SwiftUI Beta 7* 如何使 ForEach 循环中的项目处于活动状态
Posted
技术标签:
【中文标题】*SwiftUI Beta 7* 如何使 ForEach 循环中的项目处于活动状态【英文标题】:*SwiftUI Beta 7* How to give item in ForEach Loop an active state 【发布时间】:2019-09-14 19:42:01 【问题描述】:我有一个类型的数据模型:
struct fruit: Identifiable
var id = UUID()
var a: String
var b: String
var isActive: Bool
还有一个数组:
let fruitData=[
Model(a:"appleImg", b:"Apple", isActive: true),
Model(a:"pearImg", b:"Pear", isActive: false),
Model(a:"bananaImg", b:"Banana", isActive: false),
]
有一个如下所示的 RowView:
struct RowView
var a = "appleImg"
var b = "Apple"
var isActive = true
var body: some View
HStack(spacing:8)
Image(a)
Text(b)
Spacer()
然后,我创建了一个视图以在其中使用 ModelArray
并将其循环到主视图的 ForEach
中。所以像:
let fruits = fruitData
ForEach(fruits)fruitPiece in
RowView(a:fruitPiece.a, b:fruitPiece.b, isActive:
fruitPiece.isActive)
我想根据用户点击所选行来更改isActive
- 诀窍是它应该是一个选择,因此一次只有一个活动状态。对 SwiftUI 来说还是新手,因此非常感谢您的帮助:)
【问题讨论】:
有什么问题?您找不到index
吗?你不能改变数组的元素?属性是恒定的?运行时错误或构建时间?要不然是啥?这里出现了很多问题。
老实说,您的问题含糊不清——至少就实际问题而言。那么我们把SwiftUI
去掉怎么样。您的模型有一个良好的开端。还有一个(非常)好的例子,其中......我们称它为第一个元素是唯一一个活跃的元素。 (我建议更改您的示例,使每个元素在UUID
之外都是唯一的。请记住,这只是一个示例。)现在假设您希望数组中的第三个元素为isActive = true
。你会怎么做? (提示,这是基本的编码,不管是什么语言。)问题是,你没有表现出来。 (续...)
如果您可以在您的代码中向我们展示这一点,那么我们可以缩小范围。现在您有... List
(请注意,我们中的一些人仍然在 SwiftUI 中使用 UITableViews
)并希望用户点击第三个元素并...在您的模型中使用您的函数,这可能是 @987654334 @? (提示,现在使用的是 Swift、SwiftUI 和 Combine。)您在查找正在点击的单元格/行时遇到问题吗?或者转换该行以找到UUID
,这可能不是可见视图的一部分。长 cmets 短 - 这一切中哪一个是你的问题?
【参考方案1】:
下面的代码可以满足您的要求。但是首先对您的代码进行一些 cmets:
按照惯例,变量名不应以大写字母开头(例如在您的let ModelArray
中)。它使阅读变得更加困难。如果不是对你,对别人。共享代码时(例如在 *** 中),请尽量遵循适当的约定。
您正在调用 ForEach(models)
,但您尚未定义模型数组(尽管您确实创建了 ModelArray)。
在您的 ForEach 中,您正在调用 Model(...)
。在 ForEach 中,您需要一个视图来显示您的数据。但是在您的代码中,模型是一种数据类型。没有意义。
这是我认为的代码,可以满足您的要求。当您点击视图时,它的 isActive 标志会切换。为了显示它有效,文本颜色会相应改变。
struct Model: Identifiable
var id = UUID()
var a: String
var b: String
var c: String
var isActive: Bool
struct ContentView: View
@State private var modelArray = [
Model(a:"hi", b:"I like", c: "potatoes", isActive: true),
Model(a:"hi", b:"I like", c: "potatoes", isActive: false),
Model(a:"hi", b:"I like", c: "potatoes", isActive: false),
]
var body: some View
ForEach(modelArray.indices, id: \.self) idx in
Text("\(self.modelArray[idx].a) \(self.modelArray[idx].b) \(self.modelArray[idx].c)")
.foregroundColor(self.modelArray[idx].isActive ? .red : .green)
.onTapGesture
self.modelArray[idx].isActive = true
for i in self.modelArray.indices
if i != idx self.modelArray[i].isActive = false
【讨论】:
嘿,感谢您的一般提示,其中一些我已经在实际代码中完成了,但遗憾的是无法分享实际代码,所以做了一个快速示例来说明我正在尝试的内容去做!我设法做到了你在这里所做的事情,但我一直在努力只将其中一个文本行设为红色。感谢您迄今为止的帮助! 哦,我没有理解最后一个要求。我修改了代码以使选择独占。基本上,当您点击任何一行时,您会清除其余的行。或者,您可以使用单个 Int 值来指示您的哪一行是活动的,而不是为每个项目设置一个 isActive 标志。这取决于您的需求。以上是关于*SwiftUI Beta 7* 如何使 ForEach 循环中的项目处于活动状态的主要内容,如果未能解决你的问题,请参考以下文章
带有 Xcode 11 beta 7 的 SwiftUI 未更新 List / ForEach 的内容
MR_importFromObject 方法在 XCode 7.1 beta (Swiftui 2.0) 中不起作用
如何使 CocoaPods 项目在 OS X El Capitan 和 Xcode 7 Beta 上运行?