存储在数组中并显示在 UITableView 中的 UISearchBar 结果与我的 didSelectRowAt indexPath 方法混淆 (Swift)
UISearchBar results stored in an Array and displayed in a UITableView are messing with my didSelectRowAt indexPath method (Swift)
我有一个 UITableView,其中填充了标题数组中的项目,我对其进行了设置,以便在调用 didSelectRowAt indexPath 时,名为 arrayIndex 的变量更改为 indexPath 和下一个 VC 已更改。
因此,如果用户点击:
- 第 0 行 > VC 将具有标题 0、定义 0 和 Link 0
- 第 12 行 > VC 将包含标题 12、定义 12 和 Link 12
我有一个搜索栏,但是它将过滤后的结果存储在 searchResults 数组中并将它们显示在 tableView 中。当执行搜索时,数组索引将不再对应,所以如果搜索查询将tableview更改为
- 第 0 行的标题 4 > VC 将具有标题 0、定义 0 和 Link 0
- 第 1 行的标题 5 > VC 将包含标题 1、定义 1 和 Link 1
- 第 2 行的标题 18 > VC 将包含标题 2、定义 2 和 Link 2
我明白为什么它没有按预期工作,但我不确定如何更新我的逻辑来修复它。想法?这是我的代码:
列表控制器:
import UIKit
var arrayIndex = 0 // is used in DefinitionController to determine which title/definition/link to show.
var isSearching = false
class ListController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
@IBOutlet var tableView: UITableView!
@IBOutlet var searchBar: UISearchBar!
// Search Delegate
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == "" {
isSearching = false
tableView.reloadData()
} else {
isSearching = true
searchResults = (titles.filter { [=11=].lowercased().contains(searchText.lowercased()) })
tableView.reloadData()
}
}
//Table Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if isSearching == true {
// code to run if searching is true
} else {
arrayIndex = indexPath.row // assigns the value of the selected tow to arrayIndex
}
performSegue(withIdentifier: "segue", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
// Table Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching == true {
return searchResults.count
} else {
return titles.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Cell Data Source
let cell = UITableViewCell()
if isSearching == true {
cell.textLabel?.text = searchResults[indexPath.row]
} else {
cell.textLabel?.text = titles[indexPath.row]
}
// Cell Visual Formatting
cell.backgroundColor = UIColor(red:0.05, green:0.05, blue:0.07, alpha:0)
cell.textLabel?.textColor = UIColor.white
cell.textLabel?.font = UIFont(name: "Raleway", size: 18)
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
// if (cell.isSelected) {
// cell.backgroundColor = UIColor.cyan
// }else{
// cell.backgroundColor = UIColor.blue
// }
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "\(titles.count) Definitions"
// TextField Color Customization
let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField
searchBarStyle?.textColor = UIColor.white
searchBarStyle?.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:0.05)
}
}
定义控制器:
import UIKit
class DefinitionController: UIViewController {
@IBOutlet var definitionTitle: UILabel!
@IBOutlet var definitionBody: UILabel!
@IBOutlet var definitionSources: UILabel!
// Open link in Safari
@objc func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
if let url = URL(string: "\(links[arrayIndex])") {
UIApplication.shared.openURL(url)
}
}
override func viewDidLoad() {
super.viewDidLoad()
definitionTitle.text = titles[arrayIndex]
definitionBody.text = definitions[arrayIndex]
self.title = "" // Used to be \(titles[arrayIndex])
// Sources Link
let tap = UITapGestureRecognizer(target: self, action: #selector(DefinitionController.tapFunction))
definitionSources.addGestureRecognizer(tap)
}
}
我想到了一个在我看来很肮脏的解决方案,因为它需要保留两组标题,所以我仍然很好奇是否有人知道更好的方法,但这确实有效:
如果搜索(为了避免在不需要时调用开关),在 didSelectRowAt indexPath 下,我创建了一个开关,它基本上检查所选单元格的文本并相应地设置 arrayIndex 的值。
let selectedCell = tableView.cellForRow(at: indexPath)?.textLabel!.text ?? "Undefined"
switch selectedCell {
case "Anger": arrayIndex = 0
case "Anguish": arrayIndex = 1
case "Anxiety": arrayIndex = 2
case "Annoyance": arrayIndex = 3
case "Apathy": arrayIndex = 4
default: print("Undefined Search Query")
}
标题数组最终将有大约 55 个元素,我曾希望将所有数据保存在一个单独的 Data.swift 文件中,但这是我目前唯一的解决方案。
尝试使用一个字典,其中键是您的标题,它的值是一个包含定义和 link 的字典,以及一个数组,您将在其中存储搜索结果,即搜索的键。
var dictionary = ["title 0":["definition 0", "Link 0"], "title 1": ["definition 1", "Link 1"]]
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == "" {
isSearching = false
tableView.reloadData()
} else {
isSearching = true
for (key, value) in dictionary {
if key==searchText{
resultsArray.append(key)
}
}
tableView.reloadData()
}
}
现在,当您点击 List Controller
中的一个单元格时,让它知道您要在下一个 VC 中初始化和加载哪个键的详细信息:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let DefinitionViewController = self.storyboard?.instantiateViewController(withIdentifier: "DefinitionViewController") as! DefinitionViewController
//initialise data for the view controller
ListViewController.initDetails(forKey: resultsArray[indexPath.row])
performSegue(withIdentifier: "segue", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
在您的 Definition Controller
中初始化详细信息:
func initDetails(forKey key: String) {
definitionBody.text=dictionary[key]![0]
definitionSources.text=dictionary[key]![1]
}
我有一个 UITableView,其中填充了标题数组中的项目,我对其进行了设置,以便在调用 didSelectRowAt indexPath 时,名为 arrayIndex 的变量更改为 indexPath 和下一个 VC 已更改。
因此,如果用户点击:
- 第 0 行 > VC 将具有标题 0、定义 0 和 Link 0
- 第 12 行 > VC 将包含标题 12、定义 12 和 Link 12
我有一个搜索栏,但是它将过滤后的结果存储在 searchResults 数组中并将它们显示在 tableView 中。当执行搜索时,数组索引将不再对应,所以如果搜索查询将tableview更改为
- 第 0 行的标题 4 > VC 将具有标题 0、定义 0 和 Link 0
- 第 1 行的标题 5 > VC 将包含标题 1、定义 1 和 Link 1
- 第 2 行的标题 18 > VC 将包含标题 2、定义 2 和 Link 2
我明白为什么它没有按预期工作,但我不确定如何更新我的逻辑来修复它。想法?这是我的代码:
列表控制器:
import UIKit
var arrayIndex = 0 // is used in DefinitionController to determine which title/definition/link to show.
var isSearching = false
class ListController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
@IBOutlet var tableView: UITableView!
@IBOutlet var searchBar: UISearchBar!
// Search Delegate
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == "" {
isSearching = false
tableView.reloadData()
} else {
isSearching = true
searchResults = (titles.filter { [=11=].lowercased().contains(searchText.lowercased()) })
tableView.reloadData()
}
}
//Table Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if isSearching == true {
// code to run if searching is true
} else {
arrayIndex = indexPath.row // assigns the value of the selected tow to arrayIndex
}
performSegue(withIdentifier: "segue", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
// Table Data Source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching == true {
return searchResults.count
} else {
return titles.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Cell Data Source
let cell = UITableViewCell()
if isSearching == true {
cell.textLabel?.text = searchResults[indexPath.row]
} else {
cell.textLabel?.text = titles[indexPath.row]
}
// Cell Visual Formatting
cell.backgroundColor = UIColor(red:0.05, green:0.05, blue:0.07, alpha:0)
cell.textLabel?.textColor = UIColor.white
cell.textLabel?.font = UIFont(name: "Raleway", size: 18)
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
// if (cell.isSelected) {
// cell.backgroundColor = UIColor.cyan
// }else{
// cell.backgroundColor = UIColor.blue
// }
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "\(titles.count) Definitions"
// TextField Color Customization
let searchBarStyle = searchBar.value(forKey: "searchField") as? UITextField
searchBarStyle?.textColor = UIColor.white
searchBarStyle?.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:0.05)
}
}
定义控制器:
import UIKit
class DefinitionController: UIViewController {
@IBOutlet var definitionTitle: UILabel!
@IBOutlet var definitionBody: UILabel!
@IBOutlet var definitionSources: UILabel!
// Open link in Safari
@objc func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
if let url = URL(string: "\(links[arrayIndex])") {
UIApplication.shared.openURL(url)
}
}
override func viewDidLoad() {
super.viewDidLoad()
definitionTitle.text = titles[arrayIndex]
definitionBody.text = definitions[arrayIndex]
self.title = "" // Used to be \(titles[arrayIndex])
// Sources Link
let tap = UITapGestureRecognizer(target: self, action: #selector(DefinitionController.tapFunction))
definitionSources.addGestureRecognizer(tap)
}
}
我想到了一个在我看来很肮脏的解决方案,因为它需要保留两组标题,所以我仍然很好奇是否有人知道更好的方法,但这确实有效:
如果搜索(为了避免在不需要时调用开关),在 didSelectRowAt indexPath 下,我创建了一个开关,它基本上检查所选单元格的文本并相应地设置 arrayIndex 的值。
let selectedCell = tableView.cellForRow(at: indexPath)?.textLabel!.text ?? "Undefined"
switch selectedCell {
case "Anger": arrayIndex = 0
case "Anguish": arrayIndex = 1
case "Anxiety": arrayIndex = 2
case "Annoyance": arrayIndex = 3
case "Apathy": arrayIndex = 4
default: print("Undefined Search Query")
}
标题数组最终将有大约 55 个元素,我曾希望将所有数据保存在一个单独的 Data.swift 文件中,但这是我目前唯一的解决方案。
尝试使用一个字典,其中键是您的标题,它的值是一个包含定义和 link 的字典,以及一个数组,您将在其中存储搜索结果,即搜索的键。
var dictionary = ["title 0":["definition 0", "Link 0"], "title 1": ["definition 1", "Link 1"]]
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == "" {
isSearching = false
tableView.reloadData()
} else {
isSearching = true
for (key, value) in dictionary {
if key==searchText{
resultsArray.append(key)
}
}
tableView.reloadData()
}
}
现在,当您点击 List Controller
中的一个单元格时,让它知道您要在下一个 VC 中初始化和加载哪个键的详细信息:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let DefinitionViewController = self.storyboard?.instantiateViewController(withIdentifier: "DefinitionViewController") as! DefinitionViewController
//initialise data for the view controller
ListViewController.initDetails(forKey: resultsArray[indexPath.row])
performSegue(withIdentifier: "segue", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
在您的 Definition Controller
中初始化详细信息:
func initDetails(forKey key: String) {
definitionBody.text=dictionary[key]![0]
definitionSources.text=dictionary[key]![1]
}