How to put a checkmark after search

牧云@^-^@ 提交于 2020-01-25 12:02:24

问题


Im trying to put checkmarks after doing a search. I've seen some answers here but it doesn't work for me. Ive tried some of the answers but it will only make an error.

Here's the code that I wrote.

struct finalCheckednames { var name: String; var checkMark: Bool}

class ShowBroadcastNamesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {

var nameslist = ["Mark","Chris", "James", "Sandra"]
var myIndex = 0
var nameArray = String()
var filteredData = [String]()
var isSearching = false
var selectedNamesToBroadcast = [String]()
var selectedNamesIndex:Int? = nil
var checkmarks = [Int : Bool]()
var hasChecked = Bool()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? broadcastNamesTableViewCell {

        let text: String!

        if isSearching {
            text = filteredData[indexPath.row]

        } else {
            text = nameslist[indexPath.row]
        }

        cell.configureCell(text: text)

        if checkmarks[indexPath.row] != nil {
            cell.accessoryType = checkmarks[indexPath.row]! ? .checkmark : .none
        } else {
            checkmarks[indexPath.row] = false
            cell.accessoryType = .none
        }

        return cell

    } else {

        return UITableViewCell()
    }
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  if isSearching {
            selectedNamesIndex = filteredData[indexPath.row] // im also getting an error here

        } else {

    selectedNamesIndex = indexPath.row
    let cell = tableView.cellForRow(at: indexPath)

    if let index = selectedNamesIndex {
        if (cell?.accessoryType == .checkmark) {
            cell!.accessoryType = .none
            checkmarks[indexPath.row] = false
            hasChecked = false

            let indexPathTapped = tableView.indexPath(for: cell!)
            let name = nameslist[(indexPathTapped!.row)]
            print(name, hasChecked)
            if let index = selectedNamesToBroadcast.index(of: name) {
                selectedNamesToBroadcast.remove(at: index)
            }

        } else {
            cell!.accessoryType = .checkmark
            checkmarks[indexPath.row] = true
            hasChecked = true

            let indexPathTapped = tableView.indexPath(for: cell!)
            let name = nameslist[(indexPathTapped!.row)]
            print(name, hasChecked)
            selectedNamesToBroadcast.append(name)

            let selectedNamesToBroadcast = name

            finalCheckednames(name: name, checkMark: hasChecked)
            print(finalCheckednames.self, "XXXX")
        }
    }

}

 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchBar.text == nil || searchBar.text == "" {
        isSearching = false
        view.endEditing(true)
        tableView.reloadData()
    } else {
        isSearching = true
        filteredData = namelist.filter{$0.range(of: searchText, options: .caseInsensitive) != nil}
        tableView.reloadData()

I was hoping for the checkmarks to stay after searching. So atleast i can save all the checkmarked items somewhere.


回答1:


Your code is very, very, very complicated. The most efficient way to accomplish your request is to use the isChecked information in the struct, nothing else, no extra arrays, dictionaries, properties.

Give the struct and the Bool a more meaningful name.

struct Person {
    let name: String
    var isChecked: Bool
}

In the controller name the data source array people and the filter array filteredPeople. Further you need only isSearching, delete all other properties

class ShowBroadcastNamesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {

    var people = [Person(name: "Mark", isChecked: false),
                  Person(name: "Chris", isChecked: false),
                  Person(name: "James", isChecked: false),
                  Person(name: "Sandra", isChecked: false)]

    var filteredPeople = [Person]()
    var isSearching = false

var myIndex = 0
var nameArray = String()
var filteredData = [String]()
var selectedNamesToBroadcast = [String]()
var selectedNamesIndex:Int? = nil
var checkmarks = [Int : Bool]()
var hasChecked = Bool()

In cellForRow force unwrap the custom cell and name it uppercased (good practice). Pass the name to configureCell and set the accessory view depending on the value of isChecked

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! BroadcastNamesTableViewCell

    let person = isSearching ? filteredPeople[indexPath.row] : people[indexPath.row]
    cell.configureCell(text: person.name)
    cell.accessoryType = person.isChecked ? .checkmark : .none
    return cell
}

In didSelectRow toggle isChecked (and update also the people array if necessary) and reload the row, that's all

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if isSearching {
        filteredPeople[indexPath.row].isChecked.toggle()
        let index = people.firstIndex{$0.name == filteredPeople[indexPath.row].name}!
        people[index].isChecked.toggle() 
    } else {
        people[indexPath.row].isChecked.toggle()
    }
    tableView.reloadRows(at: [indexPath], with: .automatic)
}

In textDidChange search for the name

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        isSearching = false
        filteredPeople.removeAll()
        view.endEditing(true)
    } else {
        isSearching = true
        filteredPeople = people.filter{$0.name.range(of: searchText, options: .caseInsensitive) != nil}
    }
    tableView.reloadData()
 }

In this answer I already suggested a more efficient version of textDidChange, please consider to follow the advices.

To get the checked people just write

let checkedPeople = people.filter{$0.isChecked}


来源:https://stackoverflow.com/questions/57907282/how-to-put-a-checkmark-after-search

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!