Как удалить отсортированные / отфильтрованные элементы при использовании UISearchController - PullRequest
0 голосов
/ 29 мая 2020

Следующий код успешно создает, отображает список Cars в UITableView, где вы также можете позже удалить корзины. Он также представляет UISearchController, где вы можете успешно выполнять поиск.

Моя проблема заключается в попытке удалить автомобили после поиска / фильтрации, например, если пользователь выполняет поиск автомобиля, который находится в в середине массива он отобразит правую машину в верхней строке таблицы, но если он / она решит удалить его, он удалит первый элемент в массиве cars, поскольку отфильтрованный элемент всегда располагается вверху в массиве filteredCars. Здесь я не получаю ошибки, но он не удаляет нужный элемент из массива cars, он всегда удаляет первый элемент из массива cars.

Вот код:

Модель

class Car{
    var make = ""
    var model = ""
}

ViewController

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating{

    var cars =  Array<Car>()
    var filteredCars =  Array<Car>()
    let searchController = UISearchController(searchResultsController: nil)
    @IBOutlet weak var myTable: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        createCars()

        filteredCars = cars

        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search by model"
        navigationItem.searchController = searchController
        definesPresentationContext = true
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return filteredCars.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell")! as UITableViewCell
        cell.textLabel?.text = filteredCars[indexPath.row].model
        cell.detailTextLabel?.text = filteredCars[indexPath.row].make
        return cell
    }
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

        let delete = UITableViewRowAction(style: .destructive, title: "Delete") { action, index in
            let alert = UIAlertController(title: "Delete selected car?", message: "This will permanently delete the selected car, do you want to continue?", preferredStyle: UIAlertController.Style.alert)

            alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
            alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.destructive, handler: { action in
                self.filteredCars.remove(at: indexPath.row)
                self.cars.remove(at: indexPath.row)
                self.myTable.deleteRows(at: [indexPath], with: UITableView.RowAnimation.left)
            }
            ))
            self.present(alert, animated: true, completion: nil)
        }
        return [delete]
    }

    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filteredCars = searchText.isEmpty ? cars : cars.filter({(dataString: Car) -> Bool in
                return dataString.model.lowercased().contains(searchText.lowercased())
            })
            myTable.reloadData()
        }
    }
    // create cars manually for demonstration only      
    func createCars(){
        let car1 = Car()
        car1.make = "Ford"
        car1.model = "Explorer"

        //... more cars here

        cars.append(contentsOf: [car1, car2, car3, car4])
    }
}

Я пробовал следующее, но все время получаю ошибку Index out of range.

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let delete = UITableViewRowAction(style: .destructive, title: "Delete") { action, index in
        let alert = UIAlertController(title: "Delete selected car?", message: "This will permanently delete the selected car, do you want to continue?", preferredStyle: UIAlertController.Style.alert)

        alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.destructive, handler: { action in

            self.filteredCars.remove(at: indexPath.row)
            self.myTable.deleteRows(at: [indexPath], with: UITableView.RowAnimation.left)

            for i in 0..<self.cars.count {
                if self.cars[i].model == modelToDelete{
                    self.cars.remove(at:i)
                }
            }
        }
        ))
        self.present(alert, animated: true, completion: nil)
    }
    return [delete]
}

Что было бы правильным logi c для удаления элементов после поиска?

1 Ответ

1 голос
/ 29 мая 2020

Вы должны получить индекс в основном массиве для данной машины.

alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.destructive, handler: { action in
     let carToDelete = self.filteredCars.remove(at: indexPath.row)
     self.cars.remove(at: self.cars.index(of: carToDelete)!)
     tableView.deleteRows(at: [indexPath], with: .left)
}

Для этого требуется, чтобы Car принял Equatable, что довольно легко реализовать. Если вы измените class на struct, вы получите Equatable бесплатно.

class Car : Equatable {
    var make = ""
    var model = ""

    static func == (lhs: Car, rhs: Car) -> Bool {
        return lhs.make == rhs.make && lhs.model == rhs.model
    }
}

И всегда используйте экземпляр представления таблицы, переданный в качестве параметра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...