Data model
struct ActionResult: Codable {
let data: [Datum]
}
struct Datum: Codable {
let goalTitle, goalDescription, goalImage: String
let action: [Action]
}
struct Action: Codable {
let actionTitle: String
let actionGoal: String
let actionImage: String
Code
var action: Action? // this is for the segue
var result: ActionResult? {
didSet {
guard let result = result else { return }
allSectionDataActionMap = Dictionary(uniqueKeysWithValues: result.data.enumerated().map { ($0.0, ($0.1, $0.1.action)) })
updateFilteredData()
}
}
var allSectionDataActionMap = [Int: (datum: Datum, actions: [Action])]()
// Maps the section index to the Datum & filtered [Action]
var filteredSectionDataActions = [Int: (datum: Datum, actions: [Action])]()
let searchController = UISearchController()
override func viewDidLoad() {
super.viewDidLoad()
title = "Search"
searchController.searchBar.delegate = self
navigationItem.searchController = searchController
parseJSON()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return filteredSectionDataActions.count
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredSectionDataActions[section]?.actions.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ActionTableView.dequeueReusableCell(withIdentifier: "ActionCell", for: indexPath) as! ActionTableCell
let action = filteredSectionDataActions[indexPath.section]?.actions[indexPath.row]
// setup cell for action
cell.actionItem.text = action?.actionTitle
cell.actionImage.image = UIImage(named: action!.actionImage)
cell.actionImage.layer.cornerRadius = cell.actionImage.frame.size.width / 2
cell.actionGoal.text = action?.actionGoal
return cell
}
// Mark: This code is to implement the searchBar
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
updateFilteredData(for: searchText.lowercased())
tableView.reloadData()
}
func updateFilteredData(for searchText: String = String()) {
if searchText.isEmpty {
filteredSectionDataActions = allSectionDataActionMap
} else {
for (index, (datum, actions)) in allSectionDataActionMap {
let filteredActions = actions.filter { $0.actionTitle.lowercased().contains(searchText) }
if filteredActions.isEmpty {
filteredSectionDataActions[index] = (datum, actions)
} else {
filteredSectionDataActions[index] = (datum, filteredActions)
}
}