[英]How to add a Search Bar in Swift?
I'm trying to add a search bar in this pokedex.我正在尝试在此图鉴中添加一个搜索栏。 I want to add a search bar which filters out data when typed.
我想添加一个搜索栏,在输入时过滤掉数据。 The search bar doesn't filter out data when typed.
搜索栏在键入时不会过滤掉数据。 I'm new to programming so really not sure where I'm wrong.
我是编程新手,所以真的不确定我错在哪里。 Any help would be much appreciated.
任何帮助将非常感激。 Here's my code
这是我的代码
import UIKit
class PokemonListViewController: UITableViewController, UISearchBarDelegate {
@IBOutlet var searchBar: UISearchBar!
var pokemon: [PokemonListResult] = []
var filteredData: [PokemonListResult] = []
var pokeSearch = false
func capitalize(text: String) -> String {
return text.prefix(1).uppercased() + text.dropFirst()
}
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
guard let url = URL(string: "https://pokeapi.co/api/v2/pokemon?limit=151") else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {
return
}
do {
let entries = try JSONDecoder().decode(PokemonListResults.self, from: data)
self.pokemon = entries.results
self.filteredData = self.pokemon
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch let error {
print(error)
}
}.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if pokeSearch {
return filteredData.count
} else {
return pokemon.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PokemonCell", for: indexPath)
if pokeSearch {
cell.textLabel?.text = capitalize(text: filteredData[indexPath.row].name)
} else {
cell.textLabel?.text = capitalize(text: pokemon[indexPath.row].name)
}
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowPokemonSegue",
let destination = segue.destination as? PokemonViewController,
let index = tableView.indexPathForSelectedRow?.row {
destination.url = pokemon[index].url
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == " " || searchBar.text == nil {
pokeSearch = false
tableView.reloadData()
} else {
//let lower = searchBar.text!.lowercased()
//filteredData = pokemon.filter({$0.name.range(of: lower) != nil})
filteredData = pokemon.filter({pokemon -> Bool in
pokemon.name.contains(searchText)
})
pokeSearch = true
tableView.reloadData()
}
}
}
}
PokemonViewController口袋妖怪视图控制器
import UIKit导入 UIKit
class PokemonViewController: UIViewController { var url: String! class PokemonViewController: UIViewController { var url: String!
@IBOutlet var nameLabel: UILabel!
@IBOutlet var numberLabel: UILabel!
@IBOutlet var type1Label: UILabel!
@IBOutlet var type2Label: UILabel!
func capitalize(text: String) -> String {
return text.prefix(1).uppercased() + text.dropFirst()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
nameLabel.text = ""
numberLabel.text = ""
type1Label.text = ""
type2Label.text = ""
loadPokemon()
}
func loadPokemon() {
URLSession.shared.dataTask(with: URL(string: url)!) { (data, response, error) in
guard let data = data else {
return
}
do {
let result = try JSONDecoder().decode(PokemonResult.self, from: data)
DispatchQueue.main.async {
self.navigationItem.title = self.capitalize(text: result.name)
self.nameLabel.text = self.capitalize(text: result.name)
self.numberLabel.text = String(format: "#%03d", result.id)
for typeEntry in result.types {
if typeEntry.slot == 1 {
self.type1Label.text = typeEntry.type.name
}
else if typeEntry.slot == 2 {
self.type2Label.text = typeEntry.type.name
}
}
}
}
catch let error {
print(error)
}
}.resume()
}
} }
Pokemon
import Foundation
struct PokemonListResults: Codable {
let results: [PokemonListResult]
}
struct PokemonListResult: Codable {
let name: String
let url: String
}
struct PokemonResult: Codable {
let id: Int
let name: String
let types: [PokemonTypeEntry]
}
struct PokemonTypeEntry: Codable {
let slot: Int
let type: PokemonType
}
struct PokemonType: Codable {
let name: String
}
The logic is fine, but you accidentally put the textDidChange
delegate method inside the prepare
method, so that it does not get called:逻辑很好,但你不小心把
textDidChange
委托方法放在prepare
方法中,这样它就不会被调用:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowPokemonSegue",
let destination = segue.destination as? PokemonViewController,
let index = tableView.indexPathForSelectedRow?.row {
destination.url = pokemon[index].url
} //HERE -> this closes the if-statement, not the method !!
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
Just fix the curly braces.只需修复花括号。 Also, note two things:
另外,请注意两点:
let searchBarText = searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines)
and then checking if searchBarText == "" { //... } else {...}
to get rid of empty inputs and reload the data when cleared using the search bar's x buttonlet searchBarText = searchBar.text?.trimmingCharacters(in: .whitespacesAndNewlines)
然后检查if searchBarText == "" { //... } else {...}
以摆脱清空输入并在使用搜索栏的x按钮清除时重新加载数据
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.