问题
My issue
When I deal with UITableView
, I basically have an Array table_data
with my sections and rows.
[
{
title : "section A title",
rows: [
{data: row_1_data},
{data: row_2_data}
]
},
{
title : "section B title",
rows: [
{data: row_1_data},
{data: row_2_data}
]
},
]
I use heightForHeaderInSection
, cellForRowAtindexPath
, titleForHeaderInSection
, didSelectRowAtindexPath
methods like this
if indexPath.section == 0 {
//section A
if indexPath.row == 0 {
//do something with table_data[0]["rows"][0]["data"]
}
elesif indexPath.row == 1 {
//do something else
}
}
if indexPath.section == 1 {
//do something for section B
}
Working with numbers 0
, 1
, etc becomes a headache, when my table_data
array is dynamic. Dynamic means, that some sections or rows can have different positions or don't exist at all.
For example, I remove A section and my array is
[
{
title : "section B title",
rows: [
{data: row_1_data},
{data: row_2_data}
]
}
]
I do like this
self.section_A_position = 0
self.section_B_position = 1
func afterRemoveSectionA() {
section_A_position = -999
section_B_position = section_B_position - 1
//write here another new sections for -1
}
Add another section C as 0 element
self.section_C_position = -999
func afterAddSectionC() {
section_C_position = 0
section_A_position = section_A_position + 1
section_B_position = section_B_position + 1
}
And then use section_positions
in functions
if indexPath.section == section_A_position {
//section A
if indexPath.row == 0 {
//do something with table_data[0]["rows"][0]["data"]
}
elesif indexPath.row == 1 {
//do something else
}
}
if indexPath.section == section_B_position {
//do something for section B
}
It looks pretty simple, but when I have many sections and many cases to hide or move it in array, it becomes difficult to control and add new types of sections. Sometimes I create section_positions_map
array to store it together and make +1
, -1
operation in loop. But it doesn't help it is still difficult to organize it in every TableViewController, when I need this behavior.
Question
Do you know any approaches or frameworks that make this part easier?
My Ideas
- Add
type
property to my Dictionaries
{
title : "section A title",
rows: [
{data: row_1_data},
{data: row_2_data}
]
type : "section_a"
}
and check if table_data[0]["type"] == "section_a"
(or use enum
to collect types)
- Subclass my Dictionary and check
if table_data[0] is SubClassSectionA
but both of them looks ugly for me.
回答1:
An approach I use when creating a table where I know all the possible sections is with enums. You create an enum for each of the possible section types:
enum SectionTypes { case sectionA, sectionB, sectionC }
And then create a variable to hold the sections:
var sections: [SectionTypes]
When you have your data ready then you populate sections with the sections that needs to be displayed. I usually also make a method to help get the section:
func getSection(forSection: Int) -> SectionTypes {
return sections[forSection]
}
With this in place you can start implementing the common DataSource delegate methods:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return sections.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch getSection(forSection: section) {
case .sectionA:
return 0 //Add the code to get the count of rows for this section
case .sectionB:
return 0
default:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch getSection(forSection: indexPath.section) {
case .sectionA:
//Get section A cell type and format as your need
//etc
}
}
回答2:
It is a bad practice to use NSDictionary for storing data. Create new class for section (i.e. SectionData) and row (i.e. RowData). Your ViewController (or some other data provider) will keep array of SectionData, where SectionData keeps array of RowData. RowData may contain func for handling row selection, so in didSelectRowAtindexPath you just do something like this:
let rowData = rowDataAtIndexPath(indexPath)
rowData.tapHandler()
where rowDataAtIndexPath is your defined function that gives you data for indexPath.
When you need to remove some section, just remove it from array of sections and reload tableView.
回答3:
I think this talk is broader than what you are seeking but he talks about it.
https://realm.io/news/altconf-benji-encz-uikit-inside-out-declarative-programming/
来源:https://stackoverflow.com/questions/40128423/how-to-deal-with-dynamic-sections-and-rows-in-ios-uitableview