mur*_*adi 1 foreach toggle swift swiftui
我希望我能清楚地解释我的问题。
我想通过切换从列表中选择一些课程,但无论我尝试过什么,它都不起作用。
我应该做些什么?
感谢您的时间。最好的,穆拉特
struct SubjectCardsView: View {
// MARK: - Properties
@State var courses: [Course] = Bundle.main.decode("courses.json")
@State private var toggle: Bool = false
// MARK: - Body
var body: some View {
NavigationView {
List {
ForEach(courses) { course in
Section(header: Text(course.title).font(.system(size: 15, weight: .medium, design: .rounded)).foregroundColor(.blue)) {
ForEach(course.courseName, id: \.name) { item in
Toggle(isOn: $toggle, label: {
Text(item.name)
})
}
}
}
}
.listStyle(InsetGroupedListStyle())
.navigationBarTitle("Choose your subject", displayMode: .inline).font(.system(size: 16, weight: .medium, design: .rounded))
.navigationBarItems(leading: Button(action: {
}, label: {
Text("Cancel")
}), trailing: Button(action: {
}, label: {
Text("Save")
}))
} // NavigationView
}
}
Run Code Online (Sandbox Code Playgroud)
课程部分!
import Foundation
import SwiftUI
struct Course: Codable, Identifiable {
var id: Int
var title: String
var subjectCount: String
var courseName: [Content]
var isToggled = false
private var imageName: String
var image: Image {
Image(imageName)
}
enum LessonSegment: String, CaseIterable, Identifiable {
case overview
case resources
var id: String { self.rawValue }
}
enum CodingKeys: String, CodingKey {
case id
case title
case subjectCount
case imageName
case courseName
}
}
struct Content: Codable {
var id: Int
var name: String
var content: String
var assessment: String
var notify: String
}
Run Code Online (Sandbox Code Playgroud)
你的@State private var toggle: Bool = false没有道理。你有很多课程,而不是一门课程。每门课程都应该有自己的开关,这就是您开始做的:
struct Course: Codable, Identifiable {
var isToggled = false /// here!
...
}
Run Code Online (Sandbox Code Playgroud)
要使用它,您可以在 ForEach 中引用每个 ,如下所示course:isToggled
ForEach(courses) { course in
Section(header: Text(course.title).font(.system(size: 15, weight: .medium, design: .rounded)).foregroundColor(.blue)) {
ForEach(course.courseName, id: \.name) { item in
/// here!
Toggle(isOn: course.isToggled, label: {
Text(item.name)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
然而,这行不通。course.isToggled是 a Bool,而不是Binding<Bool>Toggle 期望的 a 。
哪里可以得到Binding<Bool>?@State var courses: [Course]当然是从!抱歉双关语
Binding<>部分来自@State声明。标有 的属性@State(例如您的@State var courses: [Course])包含projectedValue具有类型的Binding<>。
您可以projectedValue通过$向属性添加 a 来访问 。所以,如果你写$courses,那就有类型Binding<[Course]>。
但是,您的切换期望Binding<Bool>,而不是Binding<[Course]>。
Bool部分的用武之地。您需要将 Binding 的值 替换[Course]为Bool。好吧,我们Bool之前有过一次,对吧?
struct Course: Codable, Identifiable {
var isToggled = false /// this is a Bool!
Run Code Online (Sandbox Code Playgroud)
每门课程都有一个isToggled,即 a Bool。从这个答案的前面开始,我们在以下内容中得到了这个ForEach:
ForEach(courses) { course in
...
/// getting the Bool, which unfortunately doesn't work (yet)
Toggle(isOn: course.isToggled, label: {
Run Code Online (Sandbox Code Playgroud)
...我们需要以某种方式将Binding<>与结合起来Bool。这意味着我们必须
$courses(获取Binding<>)isToggled还有……多达!
$courses[index].isToggled /// has type Binding<Bool>
Run Code Online (Sandbox Code Playgroud)
为了得到index,我们需要循环courses.indices而不是直接循环courses。
ForEach(courses.indices) { index in
...
/// this works!
Toggle(isOn: $courses[index].isToggled, label: {
Run Code Online (Sandbox Code Playgroud)
然后,只需将course旧代码中出现的所有 替换ForEach为courses[index]. 这是完整的工作示例:
ForEach(courses.indices) { index in
Section(header: Text(courses[index].title).font(.system(size: 15, weight: .medium, design: .rounded)).foregroundColor(.blue)) {
ForEach(courses[index].courseName, id: \.name) { item in
/// $courses[index].isToggled is a Binding<Bool>
Toggle(isOn: $courses[index].isToggled, label: {
Text(item.name)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了方便起见,您不必courses[index]每次需要 current 时都执行此操作course,您可以使用此答案Array(zip中所示的方法来循环 a 。这也为循环内的每个元素分配了一个唯一的值,因此您添加的任何转换都将顺利进行。(Int, Course)idSection
ForEach(Array(zip(courses.indices, courses)), id: \.1.id) { (index, course) in
Section(header: Text(course.title).font(.system(size: 15, weight: .medium, design: .rounded)).foregroundColor(.blue)) {
ForEach(course.courseName, id: \.name) { item in
Toggle(isOn: $courses[index].isToggled, label: {
Text(item.name)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
嗯,(Int, Course)实际上是这样(Range<Array<Course>.Index>.Element, Course),但这几乎是同一件事。
最后结果:
编辑isToggled内部Content,而不是Course:
ForEach(Array(zip(courses.indices, courses)), id: \.1.id) { (index, course) in
Section(header: Text(course.title).font(.system(size: 15, weight: .medium, design: .rounded)).foregroundColor(.blue)) {
ForEach(Array(zip(course.courseName.indices, course.courseName)), id: \.1.id) { (itemIndex, item) in
/// here!
Toggle(isOn: $courses[index].courseName[itemIndex].isToggled, label: {
Text(item.name)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2542 次 |
| 最近记录: |