- Here we gonna create a List In SwiftUI with checkboxes in row items, where user can select Multiple checkboxes And the data is managed through
ObservedObject
- There is a
Button
Called “Get Selected Values” on click of it, it will fetch the selected row of the list & print it on debugger - In this example we will be using Mock data for dataSets, In your case you can use RealDatasets from WebServer
Let’s start with code –
–
1. Create a Json File for Mock Data
Xcode->New->File->Strings.
Rename it to Movies.json
[
{
"title": "Bajrangi Bhaijaan",
},
{
"title": "Kuch Kuch Hota he",
},
{
"title": "Americal PIE",
},
{
"title": "Hang over Part 3",
},
{
"title": "Edge of Tomorrow",
},
{
"title": "Blade Runner 2049",
},
{
"title": "Inception",
},
{
"title": "The Matrix",
}
]
2. Add MovieEntity.swift for Model
Create a struct which conforms to codable & holds dataSets of JSON file
struct MovieEntity {
let title: String
var isFavorite = false
}
extension MovieEntity: Decodable {
enum CodingKeys: String, CodingKey {
case title
}
}
We will be using ObservableObject
which can be used as dataSource for the List
class MoviesModel: ObservableObject {
@Published var data: [MovieEntity] = []
init() {
self.data = MockDataJSON.movies
}
}
3. Create .swift file MockDataJSON.swift
We will be reading the data from Json & feed into the MovieEntity
with use of JSONDecoder
import Foundation
struct MockDataJSON {
static var movies: [MovieEntity] = {
let url = Bundle.main.url(forResource: "Movies", withExtension: "json")!
let data = try! Data(contentsOf: url)
let decoder = JSONDecoder()
return try! decoder.decode([MovieEntity].self, from: data)
}()
}
4. CheckBox class creation
Create a checkbox class which has Image Image(systemName: isChecked ? "checkmark.square.fill" : "square")
So based on isChecked
we are selected Checkbox image.
import SwiftUI
struct CheckBoxView: View {
let isChecked: Bool;
var body: some View {
Image(systemName: isChecked ? "checkmark.square.fill" : "square")
.foregroundColor(isChecked ? Color(UIColor.systemBlue) : Color.secondary)
}
}
struct CheckBoxView_Previews: PreviewProvider {
static var previews: some View {
Group {
CheckBoxView(isChecked: true)
CheckBoxView(isChecked: false)
}
.padding()
.previewLayout(.sizeThatFits)
}
}
5.Set up the cell of List
Create a file named ListItemCell.swift which contains the row item of List. It contains the CheckBox & title
import SwiftUI
struct ListItemCell: View {
@ObservedObject var movie:MoviesModel
var currentIndex:Int = 0
var body: some View {
HStack {
Button(action: { self.movie.data[currentIndex].isFavorite.toggle() }) {
CheckBoxView(isFilled: movie.data[currentIndex].isFavorite)
}
Text(movie.data[currentIndex].title)
Spacer()
}
}
}
struct ListItemCell_Previews: PreviewProvider {
static var previews: some View {
ListItemCell(movie: MoviesModel())
.padding()
.previewLayout(.sizeThatFits)
}
}
6. Create MoviesListView.swift which contains ListView
Use VStack
where we about to place List
& Button
& use of StateObject so we can listen the @published
values, Here we have used enumerated()
on Array type because we required index
of array
import SwiftUI
struct MoviesListView: View {
@StateObject var movies = MoviesModel()
var body: some View {
VStack {
List {
ForEach(Array(movies.data.enumerated()), id: \.offset) { index, element in
ListItemCell(movie: movies, currentIndex: index)
}
}
Button {
print("Selected values ----->", movies.data.filter{$0.isFavorite})
} label: {
Text("Get Selected Values")
}
}
.navigationBarTitle("All Movies")
}
}
struct MoviesView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
MoviesListView()
}
}
}
// Note: Pass data as --@State var movies: [MovieEntity] = MockDataJSON.movies
Final code is here