Swift加载Realm数据时UITableView出现重复分区如何解决
问题原因
出现同首字母重复分区、每个分区仅1行数据的核心问题出在数据加载逻辑:
loadArtists()从Realm读取数据时,没有走首字母分组流程,直接把每个联系人包装为单元素数组追加到contactsArray,直接导致每个联系人单独占一个分区- 原分组逻辑没有做首字母归一化处理,中文联系人、大小写不同的英文同首字母联系人无法被分到同一组
- 数组操作前没有清空旧数据,多次加载会出现数据重复叠加
修复步骤
- 重写
loadArtists()方法,读取Realm数据后先存入contacts数组,再统一调用分组逻辑:
func loadArtists(){ // 清空旧数据避免重复 contacts.removeAll() contactsArray.removeAll() let contactsRealm = realm.objects(ContactRealm.self) for contact in contactsRealm { guard let name = contact.artistName, let number = contact.artistPhoneNumber else { continue } contacts.append(Contact(name: name, number: number)) } // 全量数据拉取完成后执行分组 setupContacts() tableView.reloadData() }
- 优化
setupContacts()分组逻辑,增加中文转拼音、首字母大写统一处理,对齐系统通讯录分组规则:
func setupContacts() { contactsArray.removeAll() let groupedContacts = Dictionary(grouping: contacts) { contact -> Character in // 中文转拼音、去除音标、统一大写 let nameRef = NSMutableString(string: contact.name) as CFMutableString CFStringTransform(nameRef, nil, kCFStringTransformToLatin, false) CFStringTransform(nameRef, nil, kCFStringTransformStripDiacritics, false) let normalizedStr = (nameRef as String).uppercased() // 无效首字母归入#分组 return normalizedStr.first ?? "#" } // 排序:A-Z在前,#分组在最后 let sortedKeys = groupedContacts.keys.sorted { c1, c2 in if c1 == "#" { return false } if c2 == "#" { return true } return c1 < c2 } sortedKeys.forEach { key in // 分组内联系人按姓名排序 let sortedGroupContacts = groupedContacts[key]!.sorted { $0.name < $1.name } contactsArray.append(sortedGroupContacts) } }
- 简化新增联系人的回调逻辑,上传完成后直接重新拉取全量数据即可,不需要手动维护数组:
@IBAction func goToContacts(segue: UIStoryboardSegue) { guard let addVC = segue.source as? AddArtistViewController, let name = addVC.name.text, let phoneNumber = addVC.phoneNumber.text else { return } uploadContacts(contactName: name, contactNumber: phoneNumber) loadArtists() }
修复后效果
- 同首字母(支持中文拼音匹配、英文大小写兼容)的联系人自动归入同一分区
- 分区按A-Z顺序排列,无法识别首字母的联系人归入末尾#分区
- 每个分区内联系人按姓名排序,完全对齐系统原生通讯录的分组体验

内容的提问来源于stack exchange,提问作者senanindigo
相关产品推荐
相关产品推荐

