使用 UITexfield 搜索
Search using UITexfield
我想问一下。我如何搜索我从对象映射的字符串数组,而不是我想从 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 { [=10=].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
}
在您的 textFieldShouldReturn
方法中,您将删除所有名称,然后 iterating.As 结果将没有任何结果。您必须使用另一个数组来保存搜索结果。
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
那个
因此,消除混乱,您实际上是在这样做...
self.cityNames.removeAll()
for str in cityNames {
//...
cityNames.append(str)
}
您从数组中删除所有元素并尝试对其进行迭代,但由于现在数组中没有任何元素,因此没有任何可迭代的元素。
您可以使用“过滤”数组,它从“主”数组获取输入。 “过滤”数组是将显示给用户的内容
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 { [=11=].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
}
这当然意味着您需要在 table 数据源中使用 filteredCities
而不是 cityNames
;)
说了这么多。我会考虑做一些稍微不同的事情。不使用 master/filter 列表,只需使用 cities
数组作为主数组并直接对其进行过滤...
if let text = searchTextField.text, !text.isEmpty else {
cityNames = cities.filter { [=13=].name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }.map { [=13=].name }
} else {
cityNames = cities.map { [=13=].name }
}
如果速度是个问题,您可以回退到 master/filtered 的 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 { [=14=].name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }
} else {
cityFilter = cities
}
tableView.reloadData()
return true
}
如果您担心名称为 nil
的城市,那么我会 filter
原始列表,这样主列表只包含有效值
我想问一下。我如何搜索我从对象映射的字符串数组,而不是我想从 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 { [=10=].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
}
在您的 textFieldShouldReturn
方法中,您将删除所有名称,然后 iterating.As 结果将没有任何结果。您必须使用另一个数组来保存搜索结果。
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
那个
因此,消除混乱,您实际上是在这样做...
self.cityNames.removeAll()
for str in cityNames {
//...
cityNames.append(str)
}
您从数组中删除所有元素并尝试对其进行迭代,但由于现在数组中没有任何元素,因此没有任何可迭代的元素。
您可以使用“过滤”数组,它从“主”数组获取输入。 “过滤”数组是将显示给用户的内容
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 { [=11=].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
}
这当然意味着您需要在 table 数据源中使用 filteredCities
而不是 cityNames
;)
说了这么多。我会考虑做一些稍微不同的事情。不使用 master/filter 列表,只需使用 cities
数组作为主数组并直接对其进行过滤...
if let text = searchTextField.text, !text.isEmpty else {
cityNames = cities.filter { [=13=].name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }.map { [=13=].name }
} else {
cityNames = cities.map { [=13=].name }
}
如果速度是个问题,您可以回退到 master/filtered 的 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 { [=14=].name.lowercased().range(of: text, options: .caseInsensitive, range: nil, locale: nil) != nil }
} else {
cityFilter = cities
}
tableView.reloadData()
return true
}
如果您担心名称为 nil
的城市,那么我会 filter
原始列表,这样主列表只包含有效值