Ricerca…


introduzione

Una vista semplice, ampiamente utilizzata, ma molto potente che può presentare i dati in un modulo elenco utilizzando le righe e una singola colonna. Gli utenti possono scorrere verticalmente attraverso gli elementi in una vista tabella e, facoltativamente, manipolare e selezionare il contenuto.

Sintassi

  • - (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (CGFloat) tableView: (UITableView *) tableView heightForHeaderInSection: (NSInteger) sezione;

  • - (CGFloat) tableView: (UITableView *) tableView heightForFooterInSection: sezione (NSInteger);

  • - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: (NSInteger) sezione;

  • - (UIView *) tableView: (UITableView *) tableView viewForFooterInSection: (NSInteger) sezione;

  • - (UITableViewCellAccessoryType) tableView: (UITableView *) tableView accessoryTypeForRowWithIndexPath: (NSIndexPath *) indexPath

  • - (void) tableView: (UITableView *) tableView accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView willSelectRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView willDeselectRowAtIndexPath: (NSIndexPath *) indexPath

  • - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView didDeselectRowAtIndexPath: (NSIndexPath *) indexPath

  • - (UITableViewCellEditingStyle) tableView: (UITableView *) tableView editingStyleForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSString *) tableView: (UITableView *) tableView titleForDeleteConfirmationButtonForRowAtIndexPath: (NSIndexPath *) indexPath

  • - (BOOL) tableView: (UITableView *) tableView shouldIndentWhileEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView willBeginEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView didEndEditingRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSIndexPath *) tableView: (UITableView *) tableView targetIndexPathForMoveFromRowAtIndexPath: (NSIndexPath *) sourceIndexPath toProposedIndexPath: (NSIndexPath *) proposedDestinationIndexPath;

  • - (NSInteger) tableView: (UITableView *) tableView indentationLevelForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section;

  • - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView;

  • - (NSString *) tableView: (UITableView *) tableView titleForHeaderInSection: (NSInteger) sezione; // stile di carattere fisso. usa la visualizzazione personalizzata (UILabel) se vuoi qualcosa di diverso

  • - (NSString *) tableView: (UITableView *) tableView titleForFooterInSection: (NSInteger) section;

  • - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (BOOL) tableView: (UITableView *) tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (NSArray *) sectionIndexTitlesForTableView: (UITableView *) tableView;

  • - (NSInteger) tableView: (UITableView *) tableView sectionForSectionIndexTitle: (NSString *) title atIndex: (NSInteger) index;

  • - (void) tableView: (UITableView *) tableView commitEditingStyle: (UITableViewCellEditingStyle) editStyle forRowAtIndexPath: (NSIndexPath *) indexPath;

  • - (void) tableView: (UITableView *) tableView moveRowAtIndexPath: (NSIndexPath *) sourceIndexPath toIndexPath: (NSIndexPath *) destinationIndexPath;

Osservazioni

UITableView è una sottoclasse di UIScrollView . Le classi che seguono il protocollo UITableViewDelegate seguono anche il protocollo UIScrollViewDelegate . UITableView può essere utile per mostrare elenchi lunghi o indeterminati attraverso le sue celle, mentre UIScrollView è migliore per quando la dimensione delle viste da mostrare è nota in anticipo.

Celle auto dimensionanti

In iOS 8 Apple ha introdotto la cella di dimensionamento automatico. Disegna esplicitamente UITableViewCells con Autolayout e UITableView si prende cura del resto per te. L'altezza della riga viene calcolata automaticamente, per impostazione predefinita il valore di rowHeight è UITableViewAutomaticDimension.

UITableView struttura estimatedRowHeight viene utilizzata quando auto-dimensionamento delle cellule è il calcolo.

Quando si crea una cella di visualizzazione tabella con ridimensionamento automatico, è necessario impostare questa proprietà e utilizzare i vincoli per definire la dimensione della cella.

- Apple, la documentazione di UITableView

self.tableView.estimatedRowHeight = 44.0

Notare che heightForRowAtIndexPath del delegato di heightForRowAtIndexPath non è necessario se si desidera avere un'altezza dinamica per tutte le celle. Basta impostare la proprietà sopra se necessario e prima di ricaricare o caricare la vista tabella. Tuttavia, puoi impostare l'altezza specifica di una cella mentre altre sono dinamiche tramite la seguente funzione:

veloce

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch indexPath.section {
    case 1:
        return 60
    default:
        return UITableViewAutomaticDimension
    }
}

Objective-C

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  switch (indexPath.section) {
      case 1:
        return 60;
      default:
        return UITableViewAutomaticDimension;
    }  
}

Creare un UITableView

Una vista tabella è un elenco di righe che è possibile selezionare. Ogni riga viene popolata da un'origine dati. Questo esempio crea una vista tabella semplice in cui ogni riga è una singola riga di testo.

Screenshot di UITableView

Aggiungi un UITableView allo storyboard

Sebbene ci siano molti modi per creare un UITableView , uno dei più semplici è quello di aggiungerne uno a uno Storyboard. Apri lo storyboard e trascina un UITableView sul tuo UIViewController . Assicurati di utilizzare il layout automatico per allineare correttamente il tavolo (spilli su tutti e quattro i lati).

Compilare la tabella con i dati

Per visualizzare il contenuto in modo dinamico (cioè caricarlo da un'origine dati come un array, un modello Core Data, un server in rete, ecc.) Nella visualizzazione tabella è necessario impostare l'origine dati.

Creare una semplice fonte di dati

Una fonte di dati potrebbe, come detto sopra, essere qualsiasi cosa con i dati. Dipende esclusivamente da te come formattare e che cosa è in esso. L'unico requisito è che devi essere in grado di leggerlo in un secondo momento in modo da poter popolare ogni riga della tabella con i dati quando necessario.

In questo esempio, imposteremo un array con alcune stringhe (testo) come origine dati:

veloce

let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

Objective-C

// You'll need to define this variable as a global variable (like an @property) so that you can access it later when needed.
NSArray *myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];

Impostazione dell'origine dati nel View Controller

Assicurati che il tuo controller di visualizzazione sia conforme al protocollo UITableViewDataSource .

veloce

class ViewController: UIViewController, UITableViewDataSource {

Objective-C

@interface ViewController : UIViewController <UITableViewDataSource>

Non appena il controller di visualizzazione ha dichiarato che sarà conforme a UITableViewDataSource (questo è ciò che abbiamo appena fatto sopra), è necessario implementare almeno i seguenti metodi nella classe del controller di visualizzazione:

  • tableView:numberOfRowsInSection , ti chiede quante righe dovrebbe avere la tua vista tabella.

    // Swift    
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return self.myDataArray.count
    }
    
  • tableView:cellForRowAtIndexPath , richiede di creare e restituire una cella per ciascuna riga specificata in tableView:numberOfRowsInSection . Quindi, se hai detto che avevi bisogno di 10 righe, questo metodo verrà chiamato dieci volte per ogni riga e dovrai creare una cella per ciascuna di queste righe.

    // Swift    
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
         // Create a new cell here. The cellReuseIdentifier needs to match the reuse identifier from the cell in your Storyboard
         let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!
    
         // Set the label on your cell to the text from your data array
         cell.textLabel?.text = self.myDataArray[indexPath.row]
         
         return cell
     }
    

ATTENZIONE : NON puoi restituire nil per nessuna cella in cellForRowAtIndexPath: Ciò causerà l'arresto anomalo dell'app e verrà visualizzato il seguente errore nella console:

Uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

Collegamento dell'origine dati della vista tabella al controller di visualizzazione

È possibile farlo tramite il codice impostando della vostra tabella dataSource proprietà per self sul controller della vista. Oppure puoi selezionare la visualizzazione tabella nello storyboard, aprire l'ispettore Attributi, selezionare il pannello "Outlets" e trascinare da dataSource al controller di visualizzazione ( NOTA : assicurati di connetterti a UIViewCONTROLLER, non a una UIView o a un altro oggetto nel tuo UIViewController).

Gestione delle selezioni di riga

Quando un utente tocca una riga nella tua vista tabella, generalmente, vuoi fare qualcosa - per rispondere. In molte app, quando si tocca una riga, vengono visualizzate ulteriori informazioni sull'elemento selezionato. Pensa all'app Messaggi: quando tocchi la riga che mostra uno dei tuoi contatti, la conversazione con quella persona viene quindi visualizzata sullo schermo.

In or per fare ciò, è necessario conformarsi al protocollo UITableViewDelegate . Ciò è simile alla conformità al protocollo dell'origine dati. Questa volta tuttavia, lo aggiungerai accanto a UITableViewDataSource e lo separerai con una virgola. Quindi dovrebbe assomigliare a questo:

veloce

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

Objective-C

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

Non sono richiesti metodi da implementare per il delegato della vista tabella. Tuttavia, per gestire le selezioni di riga è necessario utilizzare il seguente metodo:

  • tableView:didSelectRowAtIndexPath , questo viene chiamato ogni volta che viene tableView:didSelectRowAtIndexPath una riga, che ti permette di fare qualcosa in risposta. Per il nostro esempio, stamperemo semplicemente una dichiarazione di conferma sul registro Xcode.

    // Swift    
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
         print("You tapped cell number \(indexPath.row).")
     }
    
    // Objective-C    
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
         NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
    }
    

La soluzione finale

Vedi sotto per la configurazione completa con solo codice, nessuna spiegazione.

veloce

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // Data model: These strings will be the data for the table view cells
    let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

    // cell reuse id (cells that scroll out of view can be reused) 
    let cellReuseIdentifier = "cell"

    // don't forget to hook this up from the storyboard
    @IBOutlet var myTableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Register the table view cell class and its reuse id
        myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)

        // This view controller itself will provide the delegate methods and row data for the table view.
        myTableView.delegate = self
        myTableView.dataSource = self
    }
    
    // number of rows in table view
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.myDataArray.count
    }
    
    // create a cell for each table view row
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        // create a new cell if needed or reuse an old one
        let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!

        // set the text from the data model
        cell.textLabel?.text = self.myDataArray[indexPath.row]
        
        return cell
    }
    
    // method to run when table view cell is tapped
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
}

Objective-C

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> {
    IBOutlet UITableView *myTableView;
    NSArray *myDataArray;
}

@end

ViewController.m

#import "ViewController.h"

// cell reuse id (cells that scroll out of view can be reused)
NSString * _Nonnull cellReuseIdentifier = @"cell";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Data model: These strings will be the data for the table view cells
    myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];
    
    // Register the table view cell class and its reuse id
    [myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellReuseIdentifier];
    
    // This view controller itself will provide the delegate methods and row data for the table view.
    myTableView.delegate = self;
    myTableView.dataSource = self;
}

// number of rows in table view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return myDataArray.count;
}

// create a cell for each table view row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // create a new cell if needed or reuse an old one
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
        
    // set the text from the data model
    cell.textLabel.text = myDataArray[indexPath.row];
    
    return cell;
}
    
// method to run when table view cell is tapped
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    NSLog(@"You tapped cell number %ld.", (long)indexPath.row);
}

@end

Delegato e origine dati

UITableViewDelegate viene utilizzato per controllare come viene visualizzata la tabella e UITableViewDataSource viene utilizzato per definire i dati di UITableView . Esistono due metodi obbligatori e molti facoltativi che possono essere utilizzati per personalizzare dimensioni, sezioni, intestazioni e celle in UITableView .


UITableViewDataSource

Metodi richiesti

numberOfRowsInSection: questo metodo definisce il numero di celle che verranno visualizzate in ciascuna sezione di Tableview.

Objective-C

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows for the table view. Usually populated from an array,
    // or can be statically defined.
    return self.myArray.count;
}

Swift 3

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of rows for the table view. Usually populated from an array, 
    // or can be statically defined.
    return self.myArray.count
}

cellForRowAtIndexPath: questo metodo è dove vengono create e configurate le celle di UITableView . Dovrebbe restituire un UITableViewCell o una sottoclasse personalizzata.

Nota: L'uso dequeueReusableCellWithIdentifier:forIndexPath: richiede che la classe o il pennino è stata registrata per tale identificatore utilizzando UITableView s' registerClass:forCellReuseIdentifier: o registerNib:forCellReuseIdentifier: metodi. Di solito, questo sarà fatto nel UIViewController s' viewDidLoad metodo.

Objective-C

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCustomCell" 
                                                         forIndexPath:indexPath];
    
    // All additional customization goes here
    cell.titleLabel.text = [NSString stringWithFormat:@"Title Row %lu", indexPath.row];

    return cell;
}

Swift 3

func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("MyCustomCell", forIndexPath:indexPath)
    
    // All additional customization goes here
    cell.titleLabel.text = String(format:"Title Row %lu", indexPath.row)
    
    return cell
}
Metodi opzionali

titleForHeaderInSection: definisce una stringa come titolo per ogni intestazione di sezione nella vista tabella. Questo metodo consente solo di modificare il titolo, è possibile personalizzare ulteriormente definendo la vista per l'intestazione.

Objective-C

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    switch(section) {
        case 0:
            return @"Title 1";
            break;

        case 1:
            return @"Title 2";
            break;

        default:
            return nil;
            break;
    }
}

Swift 3

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch section {
        case 0:
            return "Title 1"
        case 1:
            return "Title 2"
        default:
            return nil
    }
}

titleForFooterInSection: definisce una stringa come titolo per ogni intestazione di sezione nella vista tabella.

Objective-C

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    return @"Footer text";
}

Swift 3

func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
    return "Footer text"
}

canEditRowAtIndexPath: utilizzato per determinare se l'interfaccia utente di modifica debba essere visualizzata per la riga specificata. Dovrebbe restituire YES se la riga specificata può essere cancellata o aggiunta.

Objective-C

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

Swift 3

func tableView(_ tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    return true
}

commitEditingStyle:forRowAtIndexPath Dovrebbe eseguire il lavoro richiesto per gestire l'aggiunta o la rimozione della riga specificata. Ad esempio, rimuovere la cella da UITableView con l'animazione e rimuovere l'oggetto associato dal modello di dati della tabella.

Objective-C

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    switch (editingStyle) {
        case UITableViewCellEditingStyleInsert:
            // Insert new data into the backing data model here
            [self insertNewDataIntoDataModel];
            [tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case UITableViewCellEditingStyleDelete:
            [self removeDataFromDataModelAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        default:
            // Nothing to perform if the editingStyle was neither Insert or Delete
            break;

    }
}

Swift 3

func tableView(_ tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    switch editingStyle {
        case .Insert:
            self.insertNewDataIntoDataModel()
            tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
        case .Delete:
            self.removeDataFromDataModelAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
        default:
            // Nothing to perform if the editingStyle was neither Insert or Delete
    }
}

editActions:forRowAt Consente di aggiungere azioni o pulsanti aggiuntivi alla modalità di modifica di una riga all'interno di UITableview . Ad esempio, se si desideravano due pulsanti, un pulsante di modifica e di eliminazione quando l'utente esegue lo scorrimento per modificare la riga, si utilizzerà questo metodo.

Swift 3

override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    // In the handler you will get passed the action as well as the indexPath for 
    // the row that is being edited 
    let editAction = UITableViewRowAction(style: .normal, title: "Edit", handler: { [unowned self] action, indexPath in
        // Do something when edit is tapped
    })
    
    // Change the color of the edit action
    editAction.backgroundColor = UIColor.blue
        
    let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete", handler: { [unowned self] action, indexPath in
        // Handel the delete event
    })
        
        
    return [deleteAction, editAction]
}

UITableViewDelegate

Tutti i metodi in UITableViewDelegate sono facoltativi, ma un delegato che li implementa abiliterà funzionalità extra per UITableView .

numberOfSectionsInTableView: per impostazione predefinita restituisce 1, ma il supporto per più sezioni è abilitato restituendo un numero diverso di sezioni.

Objective-C

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.numSections;
}

Swift 3

func numberOfSectionsInTableView(_ tableView: UITableView) -> Int {
    return self.numSections
}

viewForHeaderInSection Consente la configurazione di una vista personalizzata come intestazione per la sezione.

Objective-C

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(tableView.frame), 22)];
    view.backgroundColor = [UIColor groupTableViewBackgroundColor];
    
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:12];
    label.textColor = [UIColor darkGrayColor];
    
    switch (section) {
        case 1: {
            label.text = @"Title";
            label.frame = labelFrame;
            
            UIButton *more = [[UIButton alloc] initWithFrame:btnFrame];
            [more setTitle:@"See more" forState:UIControlStateNormal];
            [more.titleLabel setFont:[UIFont systemFontOfSize:12]];
            [view addSubview:more];
        }   break;
            
        default:
            label.frame = CGRectMake(0, 0, 0, 0);
            break;
    }
    
    [view addSubview:label];
    return view;
}

Swift 3

func tableView(_ tableView: UITableView,  viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 22))
    view.backgroundColor = UIColor.groupTableViewBackgroundColor()
    
    let label = UILabel()
    label.font = UIFont.systemFontOfSize(12)
    label.textColor = UIColor.darkGrayColor()
    
    switch section {
        case 1:
            label.text = "Title"
            label.frame = labelFrame
            
            let more = UIButton(frame: btnFrame)
            more.setTitle("See more", forState:.Normal)
            view.addSubview(more)
            
        default:
            label.frame = CGRect.zero
    }
    
    view.addSubview(label)
    return view;
}

heightForRowAtIndexPath: definisce l'altezza di ogni cella nella vista tabella.

Objective-C

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 44;
}

Swift 3

func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 44
}

heightForHeaderInSection: and heightForFooterInSection Definire l'altezza per l'intestazione e il piè di pagina di ogni sezione nella vista tabella

Objective-C

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 33;
}

Swift 3

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 33
}

Celle personalizzate

La personalizzazione di UITableViewCell può consentire interfacce molto potenti, dinamiche e reattive. Con un'ampia personalizzazione e in combinazione con altre tecniche puoi fare cose come: aggiornare proprietà specifiche o elementi dell'interfaccia mentre cambiano, animano o disegnano oggetti nella cella, caricano in modo efficiente i video mentre l'utente scorre, o persino visualizzano le immagini mentre scaricano da un Rete. Le possibilità qui sono quasi infinite. Di seguito è riportato un semplice esempio di come può apparire una cella personalizzata.

Esempio di UITableViewCell personalizzato

Questa sezione illustra le nozioni di base e, si spera, verrà ampliata per descrivere i processi più complessi come quelli descritti sopra.

Creazione della tua cella personalizzata

Innanzitutto, crea una nuova sottoclasse di UITableViewCell (crea una nuova Cocoa Touch Class in Xcode e imposta UITableViewCell come superclasse). Di seguito è riportato l'aspetto del codice dopo la sottoclasse.

veloce

class CustomTableViewCell: UITableViewCell {
    static var identifier: String {
        return NSStringFromClass(self)
    }

    var customLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        customLabel = UILabel(frame: CGRect(x: 0, y: 0, width: contentView.frame.width, height: contentView.frame.height))
        customLabel.textAlignment = .center
        contentView.addSubview(customLabel)
    }
}

Facoltativamente, selezionare "Crea anche un file XIB" quando si crea il nuovo file da personalizzare utilizzando Interface Builder. Nel caso in cui lo fai, connetti customLabel come @IBOutlet

Creare anche un file XIB

In un UIViewController contenente tableView , registra la nuova classe della cella personalizzata (vedi sotto). Nota, questo è necessario solo se non si progetta la cella con uno Storyboard nell'interfaccia della vista tabella.

veloce

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Register Cell Class
    tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: CustomTableViewCell.identifier)
}

Se si sceglie di utilizzare un file XIB, registerNib invece:

veloce

// Register Nib
tableView.register(UINib(nibName: CustomTableViewCell.identifier, bundle: nil), forCellReuseIdentifier: CustomTableViewCell.identifier)

Ora che il tuo tableView conosce la tua cella personalizzata, puoi cellForRowAtIndexPath in cellForRowAtIndexPath :

veloce

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Load the CustomTableViewCell. Make sure the identifier supplied here matches the one from your cell
    let cell: CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier(CustomTableViewCell.identifier) as! CustomTableViewCell

    // This is where the magic happens - setting a custom property on your very own cell
    cell.customLabel.text = "My Custom Cell"

    return cell
}

Espansione e compressione di UITableViewCells

Nella tua Storyboard, aggiungi un oggetto UITableView sul tuo UIViewController e lascia che copra l'intera vista. Imposta le connessioni UITableviewDataSource e UITableviewDelegate .

Objective-C

Nel tuo file .h

NSMutableArray *arrayForBool;
NSMutableArray *sectionTitleArray;

Nel tuo file .m

- (void)viewDidLoad  {
    [super viewDidLoad];

    arrayForBool = [[NSMutableArray alloc] init];
    sectionTitleArray = @[@"Sam",@"Sanju",@"John",@"Staffy"];
           
    for (int i=0; i<[sectionTitleArray count]; i++) {
        [arrayForBool addObject:[NSNumber numberWithBool:NO]];
    }

    _tableView.dataSource = self;
    _tableView.delegate = self;
}  

 // Declare number of rows in section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     if ([[arrayForBool objectAtIndex:section] boolValue]) {
         return section+2;
    } else {
         return 0; 
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
static NSString *cellid=@"hello";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellid];
if (cell==nil) {
    cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellid];
}
   BOOL manyCells  = [[arrayForBool objectAtIndex:indexPath.section] boolValue];

         /** If the section supposed to be closed******/
    if(!manyCells){
        cell.backgroundColor=[UIColor clearColor];   
        cell.textLabel.text=@"";
    }
      /** If the section supposed to be Opened******/
    else{
        cell.textLabel.text=[NSString stringWithFormat:@"%@ %d",[sectionTitleArray objectAtIndex:indexPath.section],indexPath.row+1];
        cell.backgroundColor=[UIColor whiteColor];
        cell.selectionStyle=UITableViewCellSelectionStyleNone ;
    }
cell.textLabel.textColor=[UIColor blackColor];

 /** Add a custom Separator with cell*/
  UIView* separatorLineView = [[UIView alloc]initWithFrame:CGRectMake(15, 40, _expandableTableView.frame.size.width-15, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:separatorLineView];
return cell;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [sectionTitleArray count];
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath  *)indexPath
{

/*************** Close the section, once the data is selected ***********************************/
[arrayForBool replaceObjectAtIndex:indexPath.section withObject:[NSNumber numberWithBool:NO]];

 [_expandableTableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic];

 }

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[arrayForBool objectAtIndex:indexPath.section] boolValue]) {
    return 40;
}
return 0;

   }

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{

UIView *sectionView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 280,40)];
sectionView.tag=section;
UILabel *viewLabel=[[UILabel alloc]initWithFrame:CGRectMake(10, 0, _expandableTableView.frame.size.width-10, 40)];
viewLabel.backgroundColor=[UIColor clearColor];
viewLabel.textColor=[UIColor blackColor];
viewLabel.font=[UIFont systemFontOfSize:15];
viewLabel.text=[NSString stringWithFormat:@"List of %@",[sectionTitleArray objectAtIndex:section]];
[sectionView addSubview:viewLabel];
         /********** Add a custom Separator with Section view *******************/
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(15, 40, _expandableTableView.frame.size.width-15, 1)];
separatorLineView.backgroundColor = [UIColor blackColor];
[sectionView addSubview:separatorLineView];

/********** Add UITapGestureRecognizer to SectionView   **************/

UITapGestureRecognizer  *headerTapped   = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
[sectionView addGestureRecognizer:headerTapped];

return  sectionView;


}

- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer{

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];
if (indexPath.row == 0) {
    BOOL collapsed  = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
    for (int i=0; i<[sectionTitleArray count]; i++) {
        if (indexPath.section==i) {
            [arrayForBool replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:!collapsed]];
        }
    }
    [_expandableTableView reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
    
   }
 }

Scorri per eliminare le righe

Penso sempre che sia bello avere un esempio molto semplice e autonomo in modo che nulla venga assunto quando sto imparando un nuovo compito. Questa risposta è quella per l'eliminazione di righe UITableView . Il progetto si comporta in questo modo:

gif animato che mostra scorri e cancella

Questo progetto è basato sull'esempio UITableView per Swift .

Aggiungi il codice

Crea un nuovo progetto e sostituisci il codice ViewController.swift con quanto segue.

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    // These strings will be the data for the table view cells
    var animals: [String] = ["Horse", "Cow", "Camel", "Pig", "Sheep", "Goat"]
    
    let cellReuseIdentifier = "cell"
    
    @IBOutlet var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // It is possible to do the following three things in the Interface Builder
        // rather than in code if you prefer.
        self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
        tableView.delegate = self
        tableView.dataSource = self
    }
    
    // number of rows in table view
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.animals.count
    }
    
    // create a cell for each table view row
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!
        
        cell.textLabel?.text = self.animals[indexPath.row]
        
        return cell
    }
    
    // method to run when table view cell is tapped
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
    
    // this method handles row deletion
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        
        if editingStyle == .Delete {
            
            // remove the item from the data model
            animals.removeAtIndex(indexPath.row)
            
            // delete the table view row
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
            
        } else if editingStyle == .Insert {
            // Not used in our example, but if you were adding a new row, this is where you would do it.
        }
    }

}

Il metodo a chiave singola nel codice sopra che consente l'eliminazione delle righe è l'ultimo. Eccolo di nuovo per enfasi:

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    
    if editingStyle == .Delete {
        
        // remove the item from the data model
        animals.removeAtIndex(indexPath.row)
        
        // delete the table view row
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    }
}

storyboard

Aggiungi UITableView al controller di visualizzazione nello storyboard. Utilizzare il layout automatico per fissare i quattro lati della vista tabella ai bordi del controller di visualizzazione. Controllo del trascinamento dalla visualizzazione tabella nello storyboard alla @IBOutlet var tableView: UITableView! linea nel codice.

Finito

È tutto. Dovresti essere in grado di eseguire l'app ora ed eliminare le righe scorrendo verso sinistra e toccando "Elimina".

Gli appunti

  • Questo è disponibile solo da iOS 8. Vedi questa risposta per maggiori dettagli.
  • Se è necessario modificare il numero di pulsanti visualizzati o il testo del pulsante, consultare questa risposta per ulteriori dettagli.

Ulteriori letture

Linee di separazione

Modifica della larghezza delle linee di separazione

Puoi impostare che le linee di separazione della vista tabella si estendano su varie larghezze della tabella cambiando il layoutMargins: proprietà sulle celle. Questo può essere raggiunto in diversi modi.

Modifica delle linee di separazione per celle specifiche

Nella tabella visualizza il valore cellForRowAtIndexPath: metodo o willDisplayCell: metodo, imposta il layoutMargins: della cella layoutMargins: proprietà su UIEdgeInsetsZero (si estende a tutta la larghezza della tabella) o su qualsiasi cosa tu desideri qui.

Objective-C

[cell setLayoutMargins:UIEdgeInsetsZero];

// May also use separatorInset
[cell setSeparatorInset:UIEdgeInsetsZero];

veloce

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    cell.separatorInset = UIEdgeInsetsZero
    cell.layoutMargins = UIEdgeInsetsZero
}

Rimuovi tutte le linee di separazione

Le sottili linee grigie tra ogni cella potrebbero non essere esattamente l'aspetto che stai cercando. È abbastanza semplice nasconderli dalla vista.

Nel tuo UIViewController di UIViewController comprende viewDidLoad: metodo aggiungi il seguente codice. È inoltre possibile impostare questa proprietà in qualsiasi momento prima di caricare o ricaricare la vista tabella (non necessariamente deve essere nel metodo viewDidLoad: .

Swift:

 tableView.separatorStyle = .None

Objective-C:

tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

In alternativa, la proprietà può essere modificata nello Storyboard o XIB selezionando la tabella View e l'impostazione del separator (sotto l'ispettore attributi) su None .

Nascondi le linee di separazione in eccesso

Puoi nascondere le linee del separatore di UITableViewCell per le celle vuote impostando una vista vuota del piè di pagina nella parte inferiore di UITableView:

veloce

tableView.tableFooterView = UIView()

Objective-C

tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];

Due UITableViews affiancate. Il lato sinistro dell'immagine mostra celle vuote con un separatore, il lato destro dell'immagine che mostra le celle senza un separatore.

L'immagine è di Ray Wenderlich .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow