Поиск с использованием UITexfield - PullRequest
0 голосов
/ 16 марта 2020

Я хочу спросить. Как я могу найти массив строк, которые я сопоставляю из объекта, чем я хочу найти его из uitextfield, я пытаюсь этот метод, но он не работает. где я делаю не так? вот моя настройка кода.

var cities = [City]()
var cityNames = [String]()

    private func populateCities() {
        BasicInfoServices.shared.getCity { [weak self] result in
            switch result {
            case .success(let cities):
                self?.cities = cities
                let names = cities.compactMap { $0.name }
                self?.cityNames = names
            case .failure(let error):
                print(error)
            }
        }
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: CitiesAlertCell.cellId, for: indexPath) as! CitiesAlertCell
        cell.selectionStyle = .none
        let item = cityNames[indexPath.row]
        cell.item = item
        return cell
    }

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        searchTextField.resignFirstResponder()
        cityNames.removeAll()
        return true
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if searchTextField.text?.count != nil {
            self.cityNames.removeAll()
            for str in cityNames {
                let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
                if range != nil {
                    cityNames.append(str)
                }
            }
        }
        tableView.reloadData()
        return true
    }

Ответы [ 2 ]

1 голос
/ 16 марта 2020

Итак, удаляя беспорядок, вы, по сути, делаете это ...

self.cityNames.removeAll()
for str in cityNames {
    //...
    cityNames.append(str)
}

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

Вы можете использовать «отфильтрованный» массив, который получает данные из массива «master». «Фильтрованный» массив - это то, что будет отображаться пользователю

var filteredCities: [String]()

private func populateCities() {
    BasicInfoServices.shared.getCity { [weak self] result in
        switch result {
        case .success(let cities):
            self?.cities = cities
            let names = cities.compactMap { $0.name }
            self?.cityNames = names
            self?.filteredCities = names
        case .failure(let error):
            print(error)
        }
    }
}

Затем, когда вам нужно отфильтровать список ...

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if searchTextField.text?.count != nil {
        self.filteredCities.removeAll()
        for str in cityNames {
            let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
            if range != nil {
                filteredCities.append(str)
            }
        }
    }
    tableView.reloadData()
    return true
}

Это, конечно, будет означать, что вы будете нужно использовать filteredCities вместо cityNames в вашем источнике данных таблицы;)

Сказав все это. Я бы подумал сделать что-то немного по-другому. Вместо использования списков мастер / фильтр, просто используйте массив cities как мастер и фильтруйте его напрямую ...

if let text = searchTextField.text, !text.isEmpty else { 
    cityNames = cities.filter { $0.name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }.map { $0.name }
} else {
    cityNames = cities.map { $0.name }
}

Если скорость является проблемой, вы можете вернуться к списку мастер / фильтр String значений, которые позволят вам убрать необходимость map результатов, но на этом этапе я бы задался вопросом, зачем вам нужен список String в любом случае

Например ...

var cities = [City]() // Master
var cityFilter = [City]() // Filter

private func populateCities() {
    BasicInfoServices.shared.getCity { [weak self] result in
        switch result {
        case .success(let cities):
            self?.cities = cities
            self?.cityFilter = cities
        case .failure(let error):
            print(error)
        }
    }
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: CitiesAlertCell.cellId, for: indexPath) as! CitiesAlertCell
    cell.selectionStyle = .none
    let item = cityFilter[indexPath.row]
    cell.item = item // The item is now a city reference
    return cell
}

func textFieldShouldClear(_ textField: UITextField) -> Bool {
    searchTextField.resignFirstResponder()
    cityFilter = cities
    return true
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if let text = searchTextField.text, !text.isEmpty else { 
        cityFilter = cities.filter { $0.name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }
    } else {
        cityFilter = cities
    }
    tableView.reloadData()
    return true
}

Если вы беспокоитесь о городах с nil названиями, то я бы filter исходный список, так что основной список содержал только допустимые значения

1 голос
/ 16 марта 2020

В вашем методе textFieldShouldReturn вы удаляете все имена и затем выполняете итерацию. В результате результатов не будет. Вы должны использовать другой массив для хранения результатов поиска.

var filteredCityNames = [String]()

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        filteredCityNames = []
        if searchTextField.text?.count != nil {
            for str in cityNames {
                let range = str.lowercased().range(of: textField.text!, options: .caseInsensitive, range: nil, locale: nil)
                if range != nil {
                    filteredCityNames.append(str)
                }
            }
        }
        tableView.reloadData()
        return true
    }

Вы можете использовать это filteredCityNames для этого

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