在TableView-Swift中使用JSON对象搜索栏


class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate,UISearchDisplayDelegate{
@IBOutlet weak var recipeTable: UITableView!
@IBOutlet weak var searchbarValue: UISearchBar! 
// search functionality
var filteredAnswers: [JSON]?

func searchBarSearchButtonClicked(_ searchBar: UISearchBar){
self.filteredAnswers?.removeAll()
if (searchBar.text?.isEmpty)! {
self.filteredAnswers = self.recipes     } else {
if self.recipes.count > 0 {
for i in 0...self.recipes.count - 1 {
let answer = self.recipes[i] as [Dictionary<String, AnyObject>]
if answer.title.range(of: searchBar.text!, options: .caseInsensitive) != nil {
self.filteredAnswers.append(answer)
}
}
}
}
recipeTable.reloadData();
recipeTable.reloadInputViews();
searchBar.resignFirstResponder()
}


//end search parameters

// tableview functionionalitys
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipes.count
}

// tableview functionalities
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! RecipeTableViewCell
cell.recipeLabel.text = recipes[indexPath.row].title
//cell.textLabel?.text = recipe.title
//cell.imageView?.image = recipe.imageUrl
return cell
}

// structs for json
struct Root : Decodable {
let count : Int
let recipes : [Recipe]
}
struct Recipe : Decodable { // It's highly recommended to declare Recipe in singular form
let recipeId : String
let imageUrl, sourceUrl, f2fUrl : URL
let title : String
let publisher : String
let socialRank : Double
let page : Int?
let ingredients : [String]?
}
//recipes is array of Recipes
var recipes = [Recipe]() // array of recipes
//unfiltered recipes to put into search
var filteredRecipes = [Recipe]()


fileprivate func getRecipes() {
let jsonURL = "http://food2fork.com/api/search?key=264045e3ff7b84ee346eb20e1642d9d9"
//.data(using: .utf8)!
//let somedata = Data(jsonURL.utf8)
guard let url = URL(string: jsonURL) else{return}
URLSession.shared.dataTask(with: url) {(data, response , err) in
if let response = response as? HTTPURLResponse, response.statusCode != 200 {
print(response.statusCode)
return
}
DispatchQueue.main.async {
if let err = err{
print("failed to get data from URL",err)
return
}
guard let data = data  else{return}
//print(String(data: data, encoding: .utf8))
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Root.self, from: data)
self.recipes = result.recipes
//print(result.recipes)
self.recipeTable.reloadData()
}catch let jsonERR {
print("Failed to decode",jsonERR)
}
}
}.resume()
}

override func viewDidLoad() {
super.viewDidLoad()
//search functionalities
self.searchbarValue.delegate = self
//call json object
getRecipes()
} 
}

我正在尝试实现一个搜索栏,它从JSON对象中获取成分,并在我的表视图中显示包含这些成分的食谱。我希望有一些最佳实践和帮助。我尝试了几种不同的策略,但似乎都不起作用。

这是我尝试实现的最后一个,但我在搜索功能中遇到了错误。

searchBarSearchButtonClicked中的self.recipes.count无法赋值类型为'[ViewController.Precipe]'到类型为'JSON]?

但我在-中也遇到了断言失败

[UISearchResultsTableView_dequeueReusableCellWithIdentifier:forIndexPath:usingPresentationValues:]

我希望得到帮助,但也要改进并找到最好的方法。谢谢

首先,过滤配方的逻辑无法工作,而且效率非常低。你似乎是从一个完全无关的来源复制粘贴了代码。

基本上,数据源数组的类型和筛选数组的类型必须相同,因此必须使用filteredRecipes而不是filteredAnswers

使用filtercontains过滤具有匹配成分的配方

func searchBarSearchButtonClicked(_ searchBar: UISearchBar){
filteredRecipes.removeAll()
if let searchText = searchBar.text, !searchText.isEmpty {
self.filteredRecipes = self.recipes.filter { recipe in 
guard let ingredients = recipe.ingredients else { return false }
return ingredients.contains { $0.range(of: searchText, options: .caseInsensitive) != nil }
}
} else {
self.filteredRecipes = self.recipes 
} 
recipeTable.reloadData();
recipeTable.reloadInputViews();
searchBar.resignFirstResponder()
}

实际上,这个代码应该在委托方法中执行

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)

而不是searchBarSearchButtonClicked

非常重要的是,您必须添加一个布尔属性来指示isSearching,并且在所有相关的数据源和委托方法中,如果isSearching为true,则必须添加一条条件来显示filteredRecipes的数据。

最新更新