swift - 在 ForEach 迭代中将数据传递到自定义视图 (SwiftUI)
问题描述
问题的背景:我正在创建一个简单的应用程序,它将活动数据存储在一个结构中。我创建了一个名为“CardView”的自定义视图(保存在项目中的单独文件中),它将出现在基本的 ContentView 上。CardView 填充了文本标签,这些标签将绑定到上述活动数据结构中的相应数据。ForEach 根据存在多少活动“项目”来处理这些卡片的动态创建。见以下代码...
struct ActivityItem: Identifiable, Codable {
let id = UUID()
let name: String
let description: String
let type: String
var amount: Int
}
class AppData: ObservableObject {
@Published var activites: [ActivityItem] {
didSet {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(activites) {
UserDefaults.standard.set(encoded, forKey: "Activites")
}
}
}
init() {
if let foundActivities = UserDefaults.standard.data(forKey: "Activites") {
let decoder = JSONDecoder()
if let decoded = try? decoder.decode([ActivityItem].self, from: foundActivities) {
self.activites = decoded
return
}
}
self.activites = []
}
}
struct ContentView: View {
@ObservedObject var appData = AppData()
@State private var showingAddActivity = false
@State private var showingMoreInfo = false
var body: some View {
NavigationView {
ZStack {
Rectangle()
.fill(Color(.gray))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
ScrollView {
VStack(spacing: 50) {
ForEach(appData.activites) { activity in
CardView(appData: self.appData)
}
}
}
// Below held in separate file
struct CardView: View {
@ObservedObject var appData: AppData
@State private var showingMoreInfo = false
var body: some View {
ZStack {
Rectangle()
.fill(Color(.gray))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
RoundedRectangle(cornerRadius: 20)
.fill(Color(.black))
.frame(width: 325, height: 180)
VStack {
Text("Name")
.font(.title)
Text("Description")
Text("Type")
Text("Amount")
}
.sheet(isPresented: $showingMoreInfo) {
Text("View")
}
}
}
}
问题:尽管通过使用@Binding 和利用@Environmental 进行了多次尝试和无数小时和错误,但我无法将数据从 ForEach 中的当前 ActivityItem 传递到 CardView 以用于替换文本标签中的字符串占位符(即名称、类型、金额)。当尝试创建和使用绑定时,例如 $activity.name 之类的东西,它声明“活动”不能成为绑定。我究竟做错了什么?如何以最简单的方式让每个活动将其数据传递给 CardView 结构,填充这些文本标签,然后在 ContentView“主屏幕”上创建自己 然后对 ForEach 迭代中的所有剩余对象重复?是否有任何重要的注意事项需要牢记以避免将来出现此类问题?必须补充一点,如果我将 CardView 代码直接放到 ContentView 中,而不是在 ForEach 中调用 CardView(),我可以很容易地引用数据;只有当我使用 CardView 结构时它才会成为一个问题(可重用性和减少代码混乱的长期目标)。谢谢您的帮助!
解决方案
我假设您的意思类似于以下内容(使用 Xcode 12 / iOS 14 测试)
struct ActivityItem: Identifiable, Codable {
var id = UUID()
var name: String // << made `var` here and other to allow write
var description: String
var type: String
var amount: Int
}
class AppData: ObservableObject {
@Published var activites: [ActivityItem] {
didSet {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(activites) {
UserDefaults.standard.set(encoded, forKey: "Activites")
}
}
}
init() {
if let foundActivities = UserDefaults.standard.data(forKey: "Activites") {
let decoder = JSONDecoder()
if let decoded = try? decoder.decode([ActivityItem].self, from: foundActivities) {
self.activites = decoded
return
}
}
self.activites = []
}
}
struct ContentView: View {
@ObservedObject var appData = AppData()
@State private var showingAddActivity = false
@State private var showingMoreInfo = false
var body: some View {
NavigationView {
ZStack {
Rectangle()
.fill(Color(.gray))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
ScrollView {
VStack(spacing: 50) {
ForEach(appData.activites.indices, id: \.self) { i in
CardView(item: $appData.activites[i]) // binding here
}
}
}
}
}
}
}
// Below held in separate file
struct CardView: View {
@Binding var item: ActivityItem // binding here
@State private var showingMoreInfo = false
var body: some View {
ZStack {
Rectangle()
.fill(Color(.gray))
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all)
RoundedRectangle(cornerRadius: 20)
.fill(Color(.black))
.frame(width: 325, height: 180)
VStack {
TextField("Name", text: $item.name) // edit here
.font(.title)
Text("Description")
Text("Type")
Text("Amount")
}
.sheet(isPresented: $showingMoreInfo) {
Text("View")
}
}
}
}
推荐阅读
- php - localhost 没有在 laravel 中加载项目文件
- c# - 通过 IIS 使用本地证书
- google-bigquery - BigQuery 聚簇表:在查询运行中处理的字节数不一致
- c# - 如何让 asp-action 标签助手做 http 删除?
- twitter-bootstrap - 折叠功能在 Bootstrap 3 中不起作用
- android - 当我在根路径上使用 file.listFiles() 时,它总是返回 null
- typescript - 在 Firebase HTTP 云函数中,如何在条带收费函数中将对象返回给客户端应用程序?
- html - 导航栏和英雄颜色被背景颜色隐藏
- angular - 如何将输入单选值绑定到角度对象?
- java - Netty 连接超时:没有更多信息