iOS中UITableView侧边索引标题跳转功能异常问题排查
问题原因与解决方案
核心问题分析
你遇到的索引跳转错误,本质是索引标题数组与实际分区的首字母对应关系断裂,加上索引跳转代理方法的逻辑错误,具体分两点:
1. sectionIndexTitles生成逻辑错误
你当前的代码是遍历所有歌曲,逐个添加新的电影首字母到firstLetters,最后排序得到索引标题数组。但这里存在两个问题:
- 索引标题数组的元素是所有不重复的首字母排序结果,但实际分区是按去重排序后的电影列表(
uniqueMovies)划分的,一个首字母可能对应多个分区(比如多个电影以"A"开头),导致索引数组的长度、顺序和分区的首字母分布不匹配。 - 循环内重复赋值
uniqueMovies和sectionIndexTitles,完全没必要且影响性能。
2. 索引跳转代理方法逻辑错误
你应该是直接返回了索引字母在sectionIndexTitles中的位置作为分区索引,但这个位置和实际分区中对应首字母的第一个分区位置并不一致(比如索引"D"在数组的第3位,但第一个"D"开头的分区可能在第5位),所以点击后会跳到错误的分区。
修复步骤
第一步:修正sectionIndexTitles的生成逻辑
先整理好分区数据,再从分区数据中提取不重复的首字母作为索引标题,保证索引顺序和分区的首字母顺序对应:
// 先获取去重并排序后的电影列表(这是你的分区数据源) uniqueMovies = Array(Set(songList.map { $0.movieName })).sorted() // 生成索引标题:提取每个分区电影的首字母,只保留首次出现的字母 var seenLetters = Set<String>() sectionIndexTitles = uniqueMovies.compactMap { movieName in let firstLetter = String(movieName.prefix(1)) if !seenLetters.contains(firstLetter) { seenLetters.insert(firstLetter) return firstLetter } return nil }
第二步:修正索引跳转的代理方法
实现tableView(_:sectionForSectionIndexTitle:at:)时,必须找到第一个首字母匹配的分区索引,而不是直接返回索引位置:
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int { // 遍历分区数据源,找到第一个首字母匹配的分区 for (sectionIndex, movieName) in uniqueMovies.enumerated() { let firstLetter = String(movieName.prefix(1)) if firstLetter == title { return sectionIndex } } // 未匹配到返回默认分区 return 0 }
额外优化(可选)
如果需要忽略大小写匹配(比如点击"d"也能跳到"D"开头的分区),可以统一转成大写/小写后比较:
// 生成索引标题时转大写 let firstLetter = String(movieName.prefix(1)).uppercased() // 代理方法中也转大写比较 if firstLetter == title.uppercased() { return sectionIndex }
内容的提问来源于stack exchange,提问作者Pratik Shah
相关产品推荐
相关产品推荐

