如何在此用例中向UITableView
添加节标题和索引列表?
@IBOutlet var tableView: UITableView!
var detail: Detail? = nil
var list = [tabledata]()
let search = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
list = [
tabledata(name:"something".localized, sort:"sort.something".localized, id:"something.html"),
tabledata(name:"somethingelse".localized, sort:"sort.somethingelse".localized, id:"somethingelse.html"),
...
]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "library", for: indexPath)
var data: tabledata
data = list[indexPath.row]
cell.textLabel!.text = data.name
return cell
}
现在的关键是要转换表数据。
请注意
name:
是实际的单元格名称,将是 .localized
sort:
必须帮助像单元格名称中的á
é
等字符正确排序(避免在字母末尾显示)id:
调用html文件位置以显示在detailViewController
中(“原因是必须翻译名称,我们希望在此处输入静态文本)节标题和索引列表的常规实现将导致类似
T // section header
translation // cell names
transmission
...
T // table in
Übersetzung // another language
Getriebe
...
UILocalizedIndexedCollation的正确模型是什么?
.xcodeproj 在我的github上。按需提供更多信息。
感谢帮助!
答案 0 :(得分:2)
编辑:事实证明,“考虑到每一行的第一个字母用作索引”要比考虑多种语言(尤其是非拉丁语言)时所想的要复杂得多。我正在使用UILocalizedIndexedCollation
来简化此任务。
我认为UILocalizedIndexedCollation
比滚动自己的数据模型更令人困惑。您需要2个模型:一个代表行,另一个代表节:
// UILocalizedIndexedCollation uses a selector on the `name` property
// so we have to turn this data type in to a class.
class TableRow: NSObject {
@objc var name: String
var id: String
var sectionTitle = ""
init(name: String, id: String) {
self.name = name
self.id = id
}
}
// TableSection does not have to be a class but we are making it so
// that it's consistent with `TableRow`
class TableSection: NSObject {
var title: String
var rows: [TableRow]
init(title: String, rows: [TableRow]) {
self.title = title
self.rows = rows
}
}
之后,填充和过滤表非常简单:
class Library: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var tableView: UITableView!
var detail: Detail? = nil
var list = [TableSection]()
var filter = [TableSection]()
let search = UISearchController(searchResultsController: nil)
let collation = UILocalizedIndexedCollation.current()
override func viewDidLoad() {
super.viewDidLoad()
// search
search.searchResultsUpdater = self as UISearchResultsUpdating
search.obscuresBackgroundDuringPresentation = false
search.searchBar.placeholder = "search".localized
navigationItem.hidesSearchBarWhenScrolling = false
navigationItem.searchController = search
definesPresentationContext = true
// Set the color of the index on the right of the table.
// It's settable from Interface Builder as well
tableView.sectionIndexColor = UIColor(red: 0, green: 122.0 / 255.0, blue: 1, alpha: 1)
// I took the liberty to add a few more items to the array
let rows = ["something", "somethingelse", "apple", "orange", "apricot", "strawberry"].map {
TableRow(name: $0.localized, id: $0)
}
list = organizeIntoSections(rows: rows)
tableView.reloadData()
}
// Organize rows into sections with titles
func organizeIntoSections(rows: [TableRow]) -> [TableSection] {
// Organize the rows into sections based on their `name` property
let selector: Selector = #selector(getter: TableRow.name)
// Sort the rows by `name`
let sortedRows = collation.sortedArray(from: rows, collationStringSelector: selector) as! [TableRow]
// Allocate rows into sections
var sections = collation.sectionTitles.map { TableSection(title: $0, rows: []) }
for row in sortedRows {
let sectionNumber = collation.section(for: row, collationStringSelector: selector)
sections[sectionNumber].rows.append(row)
}
// Remove empty sections
sections.removeAll(where: { $0.rows.isEmpty })
return sections
}
override func viewWillAppear(_ animated: Bool) {
if let selection = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: selection, animated: animated)
}
super.viewWillAppear(animated)
}
// MARK: - Table View
func numberOfSections(in tableView: UITableView) -> Int {
return filtering() ? filter.count : list.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
// If a section has no row, don't show its header
let data = filtering() ? filter[section] : list[section]
return data.rows.isEmpty ? nil : data.title
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filtering() ? filter[section].rows.count : list[section].rows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "library", for: indexPath)
let data = filtering() ? filter[indexPath.section].rows[indexPath.row]
: list[indexPath.section].rows[indexPath.row]
cell.textLabel!.text = data.name
return cell
}
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return filtering() ? filter.map { $0.title } : list.map { $0.title }
}
// MARK: - Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "transporter" {
if let indexPath = tableView.indexPathForSelectedRow {
let selected = filtering() ? filter[indexPath.section].rows[indexPath.row]
: list[indexPath.section].rows[indexPath.row]
let controller = (segue.destination as! Detail)
// This assumes you change `controller.result` to have type TableRow
controller.result = selected
}
}
}
// search filter
func filterContent(_ searchText: String) {
let query = searchText.lowercased()
filter = list.compactMap { section in
let matchingRows = section.rows.filter { $0.name.lowercased().contains(query) }
return matchingRows.isEmpty ? nil : TableSection(title: section.title, rows: matchingRows)
}
tableView.reloadData()
}
func searchEmpty() -> Bool {
return search.searchBar.text?.isEmpty ?? true
}
func filtering() -> Bool {
return search.isActive && (!searchEmpty())
}
}
英语:
意大利语:
斯洛伐克语
:(我从Google翻译获得翻译,所以如果有任何疑问,我会提前道歉-我不会说意大利语或斯洛伐克语)