2016-10-19 3 views
1

Ma questionComment traiter les sections et les lignes dynamiques dans iOS UITableView

Quand je traite avec UITableView, j'ai essentiellement un tableau table_data avec mes sections et des lignes.

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

J'utilise heightForHeaderInSection, cellForRowAtindexPath, titleForHeaderInSection, didSelectRowAtindexPath méthodes comme celui-ci

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 
} 

Travailler avec des numéros 0, 1, etc devient un casse-tête, quand mon tableau table_data est dynamique. Les moyens dynamiques, que certaines sections ou lignes peuvent avoir des positions différentes ou n'existent pas du tout.

Par exemple, je supprimer une section et mon tableau est

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

Je aime ce

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 
} 

Ajouter une autre section C comme 0 élément

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 
} 

Et puis utilisez section_positions dans les fonctions

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 
} 

Cela semble assez simple, mais lorsque j'ai de nombreuses sections et de nombreux cas pour le masquer ou le déplacer dans un tableau, il devient difficile de contrôler et d'ajouter de nouveaux types de sections. Parfois, je crée un tableau section_positions_map pour le stocker ensemble et faire l'opération +1, -1 en boucle. Mais cela n'aide pas, il est toujours difficile de l'organiser dans chaque TableViewController, quand j'ai besoin de ce comportement.

Question

connaissez-vous des approches ou des cadres qui font de cette partie plus facile?

Mes Idées

  1. Ajouter type propriété à mes dictionnaires
{ 
    title : "section A title", 
    rows: [ 
     {data: row_1_data}, 
     {data: row_2_data} 
    ] 
    type : "section_a" 
} 

et vérifier if table_data[0]["type"] == "section_a" (ou utiliser enum pour recueillir types)

  1. Sous-classe my Dictionar y et vérifier

if table_data[0] is SubClassSectionA

mais les deux semble laid pour moi.

Répondre

2

Une approche que je l'utilise lors de la création d'une table où je connais toutes les sections possibles est avec énumérations. Vous créez un ENUM pour chacun des types de sections possibles:

enum SectionTypes { case sectionA, sectionB, sectionC }

Et puis créer une variable pour tenir les sections:

var sections: [SectionTypes]

Lorsque vous avez vos données prêt puis vous remplissez les sections avec les sections qui doivent être affichées. D'habitude, je fais aussi une méthode pour aider à obtenir la section:

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

Avec cela en place, vous pouvez commencer à mettre en œuvre les méthodes de délégué DataSource commun:

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

C'est une mauvaise pratique d'utiliser NSDictionary pour stocker des données. Créez une nouvelle classe pour la section (c'est-à-dire SectionData) et la ligne (c'est-à-dire RowData).Votre ViewController (ou un autre fournisseur de données) conservera le tableau de SectionData, où SectionData conserve le tableau de RowData. RowData peut contenir func pour traiter la sélection de la ligne, donc en didSelectRowAtIndexPath vous venez de faire quelque chose comme ceci:

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

où rowDataAtIndexPath est votre fonction définie qui vous donne des données pour indexPath.

Lorsque vous devez supprimer une section, supprimez-la du tableau de sections et rechargez tableView.

+0

Merci pour votre réponse. C'est une façon intéressante. Mais que faire si j'ai un comportement différent pour rowData dans une section? –

+0

La fonction rowData.tapHandler peut être différente pour chaque objet ligne. Vous pouvez mettre là tout ce que vous voulez. –