我知道有一些類似的問題,但這對我不起作用。我是新手,所以我按照一些教程嘗試在我的表格視圖螢屏中創建一個搜索欄。我遇到了一個問題:索引超出范圍,我不知道為什么。這是我的代碼:
import UIKit
final class AllGroupsViewController: UITableViewController {
var groups = [
"cats",
"birds",
"dogs",
"books",
"music",
"movies",
"art",
"science",
"tech",
"beauty",
]
@IBOutlet var searchBar: UISearchBar!
var isSearching = false
var filteredData = [String]()
var userGroups: [String] = []
var groupSectionTitles = [String]()
var groupsDictionary = [String: [String]]()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(
nibName: "GroupCell",
bundle: nil),
forCellReuseIdentifier: "groupCell")
for group in groups {
let groupKey = String(group.prefix(1))
if var groupValues = groupsDictionary[groupKey] {
groupValues.append(group)
groupsDictionary[groupKey] = groupValues
} else {
groupsDictionary[groupKey] = [group]
}
}
groupSectionTitles = [String](groupsDictionary.keys)
groupSectionTitles = groupSectionTitles.sorted(by: { $0 < $1 })
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return groupSectionTitles.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isSearching {
return filteredData.count
} else {
return groups.count
}
let groupKey = groupSectionTitles[section]
if let groupValues = groupsDictionary[groupKey] {
return groupValues.count
}
return 0
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return groupSectionTitles[section]
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return groupSectionTitles
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard
let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath) as? GroupCell
else { return UITableViewCell() }
var currentGroup = groups[indexPath.row]
let groupKey = groupSectionTitles[indexPath.section]
if let groupValues = groupsDictionary[groupKey] {
currentGroup = groupValues[indexPath.row]
}
if isSearching {
currentGroup = filteredData[indexPath.row]
} else {
currentGroup = groups[indexPath.row]
}
return cell
cell.configure(
photo: UIImage(systemName: "person.3.fill") ?? UIImage(),
name: currentGroup)
return cell
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
defer {
tableView.deselectRow(at: indexPath, animated: true)
}
let groupKey = groupSectionTitles[indexPath.section]
var currentGroup = ""
if let groupValues = groupsDictionary[groupKey] {
currentGroup = groupValues[indexPath.row] // here is index out of range
}
if userGroups.firstIndex(of: currentGroup) == nil {
userGroups.append(currentGroup)
}
self.performSegue(withIdentifier: "addGroup", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addGroup",
let myGroupsViewController = segue.destination as? MyGroupsViewController {
myGroupsViewController.groups = userGroups
}
}
}
extension AllGroupsViewController {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = groups.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
isSearching = true
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
isSearching = false
searchBar.text = ""
tableView.reloadData()
}
}
如果有人會幫助我,我會很高興。而且,拜托,你能給我推薦一些好的教程來實作我的目標嗎?
uj5u.com熱心網友回復:
實際上,問題更多地與訪問組的邏輯有關,而不是由于添加了搜索欄而導致崩潰。
例如:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
if isSearching {
return filteredData.count
} else {
return groups.count
}
let groupKey = groupSectionTitles[section]
if let groupValues = groupsDictionary[groupKey] {
return groupValues.count
}
return 0
}
在這里,因為您使用if-else您將filteredData.count在搜索時回傳,或者groups.count- 您不會超出此代碼
因此,當您不搜索時,您將回傳groups.count哪個是10錯誤的,因為您想回傳我們所在部分的計數,例如a應該回傳1,b應該回傳3。
塊后 的邏輯if-else應替換else部分中的邏輯
現在看看接下來的兩個函式:
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
guard let cell
= tableView.dequeueReusableCell(withIdentifier: "groupCell",
for: indexPath) as? GroupCell
else { return UITableViewCell() }
var currentGroup = groups[indexPath.row]
let groupKey = groupSectionTitles[indexPath.section]
if let groupValues = groupsDictionary[groupKey] {
currentGroup = groupValues[indexPath.row]
}
if isSearching {
currentGroup = filteredData[indexPath.row]
} else {
currentGroup = groups[indexPath.row]
}
return cell
cell.configure(
photo: UIImage(systemName: "person.3.fill") ?? UIImage(),
name: currentGroup)
return cell
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath) {
defer {
tableView.deselectRow(at: indexPath, animated: true)
}
let groupKey = groupSectionTitles[indexPath.section]
var currentGroup = ""
if let groupValues = groupsDictionary[groupKey] {
currentGroup = groupValues[indexPath.row] // here is index out of range
}
if userGroups.firstIndex(of: currentGroup) == nil {
userGroups.append(currentGroup)
}
self.performSegue(withIdentifier: "addGroup", sender: nil)
}
首先,因為numberOfRowsInSection回傳錯誤的值,我們會在這些函式中遇到問題。
然后我認為訪問組的正確資料源的邏輯,組部分沒有做對。
例如:currentGroup = groups[indexPath.row]incellForRowAt indexPath是不正確的,因為當我們只想對特定部分進行分組時,這會從 10 的組陣列中獲取組。
而且我也看到return cell了兩次,所以第一次之后的代碼不會運行。
So what I did is just refactored these functions to make it more clear and added some comments.
First, we need to keep in mind the different data sources:
// All the groups
var groups = [
"cats",
"birds",
"dogs",
"books",
"music",
"movies",
"art",
"science",
"tech",
"beauty",
]
// Checks if search is active or not
var isSearching = false
// This will hold the filtered array when searching
var filteredData = [String]()
// This will hold groups of the user
var userGroups: [String] = []
// This will hold section prefixes [a, b, c, etc]
var groupSectionTitles = [String]()
// This will hold mapping of prefixes to groups
// [a: [art], b: [beauty, books], etc]
var groupsDictionary = [String: [String]]()
There is nothing different above from your code, only comments, however we have to keep a visual image of this because this is important to how we need to access the data
Next, I created this function to get the correct groups in a section since we need to do this many times
private func getGroups(in section: Int) -> [String]
{
// The current section should be got from groupSectionTitles
let groupKey = groupSectionTitles[section]
var groupsInSection: [String] = []
// Get groups for current section
if let groupValues = groupsDictionary[groupKey] {
groupsInSection = groupValues
}
// Change groups in section if searching
if isSearching {
groupsInSection = filteredData
}
return groupsInSection
}
Then I refactored these functions slightly:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
if isSearching {
return filteredData.count
} else {
let groupsInSection = getGroups(in: section)
return groupsInSection.count
}
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
guard let cell
= tableView.dequeueReusableCell(withIdentifier: "groupCell",
for: indexPath) as? GroupCell
else { return UITableViewCell() }
let groupsInSection = getGroups(in: indexPath.section)
cell.configure(
photo: UIImage(systemName: "person.3.fill") ?? UIImage(),
name: groupsInSection[indexPath.row])
return cell
}
override func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath)
{
let groupsInSection = getGroups(in: indexPath.section)
let currentGroup = groupsInSection[indexPath.row]
if userGroups.firstIndex(of: currentGroup) == nil {
userGroups.append(currentGroup)
}
defer {
tableView.deselectRow(at: indexPath, animated: true)
}
self.performSegue(withIdentifier: "addGroup", sender: nil)
}
I think now your crash will be resolved and things work as expected.
However, since you did not connect and implement search delegate yet, maybe there can be some issues when isSearching becomes true but I think that can be for another question on filtering with search delegate.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/426041.html
下一篇:非邏輯運算子
