如何解决在列表中切换选择 - SwiftUI Binding<> 部分来自 @State 声明这就是 Bool 部分的用武之地
我希望我能清楚地解释我的问题。
我想通过切换从列表中选择一些课程,但我尝试过的任何课程都不起作用。
我该怎么办?
感谢您的时间。 最好的, 穆拉特
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,design: .rounded))
.navigationBarItems(leading: Button(action: {
},label: {
Text("Cancel")
}),trailing: Button(action: {
},label: {
Text("Save")
}))
} // NavigationView
}
}
课程部分!
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
}
解决方法
你的 @State private var toggle: Bool = false
没有意义。你有很多课程,而不是一门课程。每门课程都应该有自己的开/关开关,这是您开始使用的:
struct Course: Codable,Identifiable {
var isToggled = false /// here!
...
}
要使用它,您可以在 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)
})
}
}
}
然而,这行不通。 course.isToggled
是 Bool
,而不是 Toggle 所期望的 Binding<Bool>
。
您从哪里可以获得Binding<Bool>
?当然来自@State var courses: [Course]
! 抱歉双关语
Binding<>
部分来自 @State
声明。
标有 @State
的属性,如您的 @State var courses: [Course]
,包括一个 Binding<>
类型的 projectedValue
。
您可以通过向属性添加 projectedValue
来访问 $
。因此,如果您编写 $courses
,则类型为 Binding<[Course]>
。
但是,您的切换需要 Binding<Bool>
,而不是 Binding<[Course]>
。
这就是 Bool
部分的用武之地。
您需要将绑定的值 [Course]
替换为 Bool
。好吧,我们之前有过 Bool
,对吗?
struct Course: Codable,Identifiable {
var isToggled = false /// this is a Bool!
每门课程都有一个isToggled
,即Bool
。从本答案的前面开始,我们在 ForEach
中得到了这个:
ForEach(courses) { course in
...
/// getting the Bool,which unfortunately doesn't work (yet)
Toggle(isOn: course.isToggled,label: {
... 我们需要以某种方式将 Binding<>
与 Bool
结合起来。这意味着我们必须
- 引用
$courses
(获取Binding<>
) - 获取每门课程的
isToggled
还有……多田!
$courses[index].isToggled /// has type Binding<Bool>
要获得 index
,我们需要循环 courses.indices
而不是直接循环 courses
。
ForEach(courses.indices) { index in
...
/// this works!
Toggle(isOn: $courses[index].isToggled,label: {
然后,只需用 course
替换旧代码 ForEach
中出现的所有 courses[index]
。这是完整的工作示例:
ForEach(courses.indices) { index in
Section(header: Text(courses[index].title).font(.system(size: 15,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)
})
}
}
}
为方便起见,您不必每次想要当前的 courses[index]
时都执行 course
,您可以使用 this answer 中所示的 Array(zip
循环(Int,Course)
。这还会为循环内的每个 id
分配一个唯一的 Section
,因此您添加的任何过渡都会顺利进行。
ForEach(Array(zip(courses.indices,courses)),id: \.1.id) { (index,course) in
Section(header: Text(course.title).font(.system(size: 15,id: \.name) { item in
Toggle(isOn: $courses[index].isToggled,label: {
Text(item.name)
})
}
}
}
好吧,(Int,Course)
实际上是 (Range<Array<Course>.Index>.Element,Course)
,但这几乎是同一回事。
最终结果:
在 isToggled
内编辑 Content
,而不是 Course
:
ForEach(Array(zip(courses.indices,course) in
Section(header: Text(course.title).font(.system(size: 15,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)
})
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。