ios - 如何实现 TextField 搜索结果以过滤 tableview 值 Swift
问题描述
我创建了一个 pickerView 来将值选择到 ViewController 顶部的自定义 textField 栏中,以过滤 UITableView 中的数据值。由于我有嵌套类型的 JSON,因此无法正确了解如何使用过滤器。
我想用 TableView 将 textField 实现为搜索栏。附上截图。
我需要过滤的值是 Parkings.Address -> textField
为文本搜索添加了 textFieldDidEndEditing 函数。
模型:
struct JSONDB: Codable {
var ParkingInfoList: [`Parkings`]
}
struct Parkings: Codable {
var Id: String
var Name: String
var Tel: String
var CarTotal: String
var CarRemaining: String
var Address: String
var ServiceTime: String
var ChargeInfo: String
var ParkinfInfo: String?
var Lat: String
var Lng: String
}
struct JSONDB2: Codable {
var ParkingCityList: [City]
}
struct City: Codable {
var CityCode: String
var CityChtName: String
var CityArea: [String]
}
JSON数据:
{
"ParkingInfoList": [
{
"Id": "K82",
"Name": "瑞湖停車場",
"Tel": "0226573430",
"Address": "文德段5小段297地號;民權東路6段15巷50號空地",
"CarTotal": "46",
"CarRemaining": "暫時無提供資訊",
"MotorTotal": "暫時無提供資訊",
"MotorRemaining": "暫時無提供資訊",
"ServiceTime": "24小時",
"ChargeInfo": "計次:50元/次,(每次以2.5小時為限)。月租:3,000元/月。",
"ParkingInfo": "一般平面式小型車46格(含身心障礙停車位2格)。",
"City": "TPE",
"Area": "內湖區",
"Lat": "25.06854351",
"Lng": "121.5769806",
"SourceUpdateTime": "2020-09-24T00:00:00"
},
视图控制器代码:
import UIKit
class SelectedTableViewController: UITableViewController, UIPickerViewDelegate, UIPickerViewDataSource,UITextFieldDelegate {
@IBOutlet weak var myTextfield: UITextField!
let myPickerView = UIPickerView()
var selectedArea = ""
var loadingData = [City]()
var parkingData = [Parkings]()
var okData : Parkings?
var searchActive = false
var arrfilter = [Parkings]()
let apiAddress = "https://lifeinfo.megatime.com.tw/lifeInfo/QueryParkingCityList.ashx"
let urlSession = URLSession(configuration: .default)
override func viewDidLoad() {
super.viewDidLoad()
self.myPickerView.delegate = self
self.myPickerView.dataSource = self
self.myTextfield.delegate = self
downloadInfo(withAddress: apiAddress)
myTextfield.inputView = myPickerView
myPickerView.showsSelectionIndicator = true
}
func downloadInfo(withAddress webAddress: String ){
if let url = URL(string: webAddress){
let task = urlSession.dataTask(with: url) { (data, response, error) in
if error != nil{
let errorcode = (error! as NSError).code
if errorcode == -1009{
print("No Internet Connection")
}else{
print("Something Wrong")
}
return
}
if let loadedData = data{
print("Got Data")
do{
let decoder = JSONDecoder()
let JSONdb = try decoder.decode(JSONDB2.self, from: loadedData)
print("JSONDB2 OK")
self.loadingData = JSONdb.ParkingCityList
DispatchQueue.main.async {
self.tableView.reloadData()
}
}catch{
print(error)
}
}
}
task.resume()
}
}
func initPickerView(touchAt sender:UITextField){
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = .systemBlue
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "check", style: .plain, target: self, action: #selector(submit))
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "cancel", style: .plain, target: self, action: #selector(cancel))
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
myTextfield.inputAccessoryView = toolBar
myTextfield.inputView = myPickerView
}
@objc func cancel(){
self.myTextfield?.resignFirstResponder()
}
@objc func submit(sender: UIBarButtonItem){
DispatchQueue.main.async { [self] in
self.myTextfield.text = "taipei \(self.selectedArea)"
self.myTextfield?.resignFirstResponder()
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0{
return 1
}
return loadingData[0].CityArea.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0{
return "taipei"
}
let test = loadingData[0].CityArea[row]
// print(test)
return test
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == self.myTextfield {
myTextfield.isHidden = false
myPickerView.removeFromSuperview()
self.initPickerView(touchAt: textField)
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
myTextfield.text = "臺北市 \(loadingData[0].CityArea[row])"
self.selectedArea = loadingData[0].CityArea[row]
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if myTextfield.text == ""{
return parkingData.count
}else {
myTextfield.text = selectedArea
}
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SelectedTableViewCell", for: indexPath) as! SelectedTableViewCell
let data = parkingData[indexPath.row]
cell.lbRemaining.text = data.CarRemaining
cell.lbName.text = data.Name
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.okData = self.parkingData[indexPath.row]
performSegue(withIdentifier: "DetailSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DetailSegue"{
let detail = segue.destination as! DetailTableViewController
detail.okData = self.okData
}
}
}
下面是我已经尝试过但失败的过滤器部分:
尝试1:谓词方式但显示错误:“无法解析格式字符串“SELF.Address CONTAINTS[C] %@””
尝试2:过滤方式但显示错误:“无法将'Parkings'类型的值转换为强制类型'NSString'”
func textFieldDidEndEditing(_ textField: UITextField) {
guard let searchText:String = myTextfield.text else {
return}
\\ try 1: predicate way but show error: "Unable to parse the format string \"SELF.Address CONTAINTS[C] %@\""
let predicate:NSPredicate = NSPredicate(format: "SELF.Address CONTAINTS[C] %@", searchText)
let array = (parkingData as NSArray).filtered(using: predicate)
print("array =\(array)")
\\ try 2: filter way but show error: "Cannot convert value of type 'Parkings' to type 'NSString' in coercion "
arrfilter = parkingData.filter({ (test) -> Bool in
let tmp: NSString = test as NSString
let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
return range.location != NSNotFound
})
if(arrfilter.count == 0){
searchActive = false;
} else {
searchActive = true;
}
self.tableView.reloadData()
}
解决方案
推荐阅读
- javascript - Nodejs错误消息不断弹出注册系统
- node.js - 如何在 socket.io 客户端中修复“未捕获的 ReferenceError:在初始化之前无法访问 'io'”?
- mysql - 使用最新数据而不是相等数据加入 SQL
- php - 如何在某些页面上获得管理员访问权限
- windows - 本网站的安全证书有问题
- primeng - p-table 动态行 PrimeNG 中的 p-dropdown - 版本 9 - Stackblitz 添加
- python - 从字符串创建一个字符列表,仅使用字符串函数而不是正则表达式
- tensorflow2.0 - 对张量流损失类 (categorical_crossentropy) 进行子分类以创建加权损失函数时,意外的关键字参数“sample_weight”
- python - 如何在 tensorflow 2.0 中创建填充批处理?
- java - R2dbc 不能使用 tcp 处理 h2 数据库