如何处理iOS UITableView中的动态Sections和Rows

时间:2016-10-19 10:14:03

标签: ios swift xcode uitableview sections

我的问题

当我处理UITableView时,我基本上有一个包含我的部分和行的数组table_data

[
   {
      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}
      ]
   },
]

我使用heightForHeaderInSectioncellForRowAtindexPathtitleForHeaderInSectiondidSelectRowAtindexPath这样的方法

 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
 }

当我的0数组是动态的时,使用数字1table_data等会变得很头疼。动态意味着某些部分或行可以具有不同的位置或根本不存在。

例如,我删除了A部分,我的数组是

[
   {
      title : "section B title",
      rows: [
          {data: row_1_data},
          {data: row_2_data}
      ]
   }
]

我喜欢这个

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 
}

将另一个C部分添加为0元素

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
}

然后在函数中使用section_positions

 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
 }

它看起来很简单,但是当我有许多部分和许多情况要隐藏或移动数组时,很难控制和添加新类型的部分。有时我会创建section_positions_map数组来将它存储在一起并在循环中进行+1-1操作。但是当我需要这种行为时,它仍然很难在每个TableViewController中组织它。

问题

您是否知道使这部分更容易的任何方法或框架?

我的想法

  1. type属性添加到我的词典
  2. {
      title : "section A title",
      rows: [
          {data: row_1_data},
          {data: row_2_data}
      ]
      type : "section_a"
    }
    

    并检查if table_data[0]["type"] == "section_a"(或使用enum收集类型)

    1. 我的词典子类并检查
    2. if table_data[0] is SubClassSectionA

      但他们两个看起来都很难看。

3 个答案:

答案 0 :(得分:5)

我在创建表时使用的方法,我知道所有可能的部分都是枚举。您可以为每个可能的部分类型创建枚举:

enum SectionTypes { case sectionA, sectionB, sectionC }

然后创建一个变量来保存部分:

var sections: [SectionTypes]

准备好数据后,就可以使用需要显示的部分填充部分。我通常也会制作一个方法来帮助获取该部分:

func getSection(forSection: Int) -> SectionTypes {
        return sections[forSection]
    }

有了这个,你就可以开始实现常见的DataSource委托方法了:

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
    }
}

答案 1 :(得分:1)

使用NSDictionary存储数据是一种不好的做法。为section(即SectionData)和row(即RowData)创建新类。您的ViewController(或其他一些数据提供程序)将保留SectionData数组,其中SectionData保留RowData数组。 RowData可能包含用于处理行选择的func,所以在didSelectRowAtindexPath中你只需执行以下操作:

let rowData = rowDataAtIndexPath(indexPath)
rowData.tapHandler()

其中rowDataAtIndexPath是您为indexPath提供数据的已定义函数。

当您需要删除某些部分时,只需将其从部分数组中删除并重新加载tableView。

答案 2 :(得分:0)

我认为这次谈话比你所寻求的更广泛,但他谈到了这一点。

https://realm.io/news/altconf-benji-encz-uikit-inside-out-declarative-programming/