UITableViewCell, mostra il pulsante Elimina sul colpo


568

Come faccio a visualizzare il pulsante Elimina quando scorro su un UITableViewCell? L'evento non viene mai generato e il pulsante Elimina non viene mai visualizzato.


1
Chiunque cerchi una risposta dettagliata e aggiornata, scorrere fino a stackoverflow.com/a/37719543/6872794
Munib,

Vedi la mia risposta Swift 4 per una domanda simile che mostra fino a 3 modi diversi per creare lo scorrimento per eliminare le azioni per UITableViewCells.
Imanou Petit,

Ho fatto questa domanda 8 anni fa ... per favore cancella questa domanda è enormemente obsoleta. Swift non esisteva nemmeno!
TheLearner

possiamo effettuare la correzione dell'altezza per i pulsanti di scorrimento laterali? ad esempio: la mia cella è 150 e voglio che il pulsante venga visualizzato solo 50.0f è possibile?
Suhas Arvind Patil,

questo funziona alla grande su righe, ma qualche indizio su come integrarlo nelle sezioni?
Frostmourne,

Risposte:


1035

Durante l'avvio in (-viewDidLoad or in storyboard)do:

self.tableView.allowsMultipleSelectionDuringEditing = NO;

Sostituisci per supportare la modifica condizionale della vista tabella. Questo deve essere implementato solo se tornerai NOper alcuni articoli. Per impostazione predefinita, tutti gli elementi sono modificabili.

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return YES if you want the specified item to be editable.
    return YES;
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //add code here for when you hit delete
    }    
}

94
Funziona, ma ... - (BOOL) tableView: (UITableView *) tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath ... deve essere implementato solo se si restituisce NO per alcuni articoli. Per impostazione predefinita, tutti gli articoli sono modificabili, quindi non è necessario implementarlo se si restituisce sempre SÌ.
Thanos Diacakis,

24
Anche importante sapere: questi sono metodi UITableViewDataSource e metodi NOT UITableViewDelegate.
Dave Albert,


12
Giusto per essere chiari: DEVI sovrascrivere tableView: commitEditingStyle: forRowAtIndexPath: altrimenti il ​​gesto di scorrimento non verrà riconosciuto e non accadrà nulla quando si tenta di eliminare.
Chris,

Questo non ha funzionato per me (all'inizio). Avevo anche bisogno di impostare self.tableView.allowsMultipleSelectionDuringEditing = NO;il funzionamento con il tocco sinistro. Mi sembra un bug perché la tabella NON è in stato di modifica. Questa opzione dovrebbe applicare solo "Durante l'editing". Tuttavia, ora funziona e l'ho impostato su SÌ ogni volta che la tabella entra nello stato di modifica.
osxdirk,

118

Questa risposta è stata aggiornata a Swift 3

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 eliminare le UITableViewrighe. Il progetto si comporta così:

inserisci qui la descrizione dell'immagine

Questo progetto si basa sull'esempio di UITableView per Swift .

Aggiungi il codice

Creare un nuovo progetto e sostituire il codice ViewController.swift con il seguente.

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.register(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, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: 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, didSelectRowAt indexPath: IndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }

    // this method handles row deletion
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

        if editingStyle == .delete {

            // remove the item from the data model
            animals.remove(at: indexPath.row)

            // delete the table view row
            tableView.deleteRows(at: [indexPath], with: .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 della riga è l'ultimo. Eccolo di nuovo per enfasi:

// this method handles row deletion
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {

        // remove the item from the data model
        animals.remove(at: indexPath.row)

        // delete the table view row
        tableView.deleteRows(at: [indexPath], with: .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.
    }
}

storyboard

Aggiungi UITableViewa al View Controller nello storyboard. Utilizzare il layout automatico per bloccare i quattro lati della vista tabella ai bordi del View Controller. Controlla il trascinamento dalla vista tabella nello storyboard alla @IBOutlet var tableView: UITableView!riga nel codice.

Finito

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


variazioni

Modifica il testo del pulsante "Elimina"

inserisci qui la descrizione dell'immagine

Aggiungi il seguente metodo:

func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
    return "Erase"
}

Azioni con pulsanti personalizzati

inserisci qui la descrizione dell'immagine

Aggiungi il seguente metodo

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

    // action one
    let editAction = UITableViewRowAction(style: .default, title: "Edit", handler: { (action, indexPath) in
        print("Edit tapped")
    })
    editAction.backgroundColor = UIColor.blue

    // action two
    let deleteAction = UITableViewRowAction(style: .default, title: "Delete", handler: { (action, indexPath) in
        print("Delete tapped")
    })
    deleteAction.backgroundColor = UIColor.red

    return [editAction, deleteAction]
}

Nota che questo è disponibile solo da iOS 8. Vedi questa risposta per maggiori dettagli.

Aggiornato per iOS 11

Le azioni possono essere posizionate all'inizio o alla fine della cella usando i metodi aggiunti all'API UITableViewDelegate in iOS 11.

func tableView(_ tableView: UITableView,
                leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
 {
     let editAction = UIContextualAction(style: .normal, title:  "Edit", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
             success(true)
         })
editAction.backgroundColor = .blue

         return UISwipeActionsConfiguration(actions: [editAction])
 }

 func tableView(_ tableView: UITableView,
                trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
 {
     let deleteAction = UIContextualAction(style: .normal, title:  "Delete", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
         success(true)
     })
     deleteAction.backgroundColor = .red

     return UISwipeActionsConfiguration(actions: [deleteAction])
 }

Ulteriori letture


grazie per gli esempi e il codice. Ora sono pronto per implementare la funzione di eliminazione. Puoi dirmi qual è lo scopo della riga "self.tableView.registerClass (..." che hai aggiunto a viewDidLoad ()? E qual è l'equivalente di quello nel builder di interfacce? Che non era nell'esempio di cella personalizzato. Sembra che stiamo specificando due volte cellReuseIdentifier, grazie!
rockhammer,

Se si include la riga .registerClass, la compilazione non riesce
rockhammer

@rockhammer, hai ragione, non è necessario (apparentemente impossibile) impostare l'identificatore di riutilizzo delle celle sia in codice che in Interface Builder. Scegli un modo in base alle tue preferenze. Anche se questo progetto si basa su quella base UITableViewuna , questo è un progetto da solo completamente stare in piedi e non c'è bisogno di fare nulla che non sia qui descritto. Il motivo per cui ho iniziato a impostarlo nel codice è che richiede meno spiegazioni nelle mie risposte. Dovrei tornare indietro e modificare l'esempio di base per usare anche il codice.
Suragch,

Come implementare un colpo giusto? Di 'un colpo di sinistra "rifiuta" qualcosa e un colpo di destra "accetta" qualcosa nella cella?
Munib,

1
@ return0, per quanto ne so, la funzionalità di scorrimento a destra non è integrata, quindi dovresti crearla da zero. Vedi questo articolo per idee per iniziare se vuoi provare. Tuttavia, non consiglierei di farlo dal momento che non è un'azione standard che un utente si aspetterebbe. Piuttosto, mostrerei due scelte di pulsanti con un tocco sinistro come nella sezione di azione dei pulsanti personalizzati nella mia risposta sopra.
Suragch,

70

Questo codice mostra come implementare l'eliminazione.

#pragma mark - UITableViewDataSource

// Swipe to delete.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [_chats removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

Facoltativamente, nella sostituzione di inizializzazione, aggiungi la riga seguente per mostrare l'elemento del pulsante Modifica:

self.navigationItem.leftBarButtonItem = self.editButtonItem;

Devi implementare quel metodo. Il contenuto all'interno dovrebbe corrispondere a qualsiasi cosa abbia senso per il tuo caso d'uso. Nel codice sopra _chats sono i dati di supporto per la vista tabella. Una volta che l'utente preme delete, il singolo oggetto chat deve essere rimosso da _chat in modo che l'origine dati rifletta quindi il nuovo conteggio delle righe (altrimenti genera un'eccezione).
ewcy,

25

Ho avuto un problema che sono appena riuscito a risolvere, quindi lo condivido perché potrebbe aiutare qualcuno.

Ho un UITableView e ho aggiunto i metodi mostrati per abilitare lo scorrimento per eliminare:

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return YES if you want the specified item to be editable.
    return YES;
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //add code here for when you hit delete
    }    
}

Sto lavorando a un aggiornamento che mi consente di mettere la tabella in modalità di modifica e abilita la selezione multipla. Per fare ciò ho aggiunto il codice dell'esempio TableMultiSelect di Apple . Una volta che ho funzionato ho scoperto che il mio colpo la funzione di eliminazione aveva smesso di funzionare.

Si è scoperto che il problema era l'aggiunta della seguente riga a viewDidLoad:

self.tableView.allowsMultipleSelectionDuringEditing = YES;

Con questa riga in, la selezione multipla funzionerebbe ma il colpo da eliminare non funzionerebbe. Senza la linea era il contrario.

La correzione:

Aggiungi il seguente metodo al tuo viewController:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    self.tableView.allowsMultipleSelectionDuringEditing = editing; 
    [super setEditing:editing animated:animated];
}

Quindi nel tuo metodo che mette la tabella in modalità di modifica (ad esempio premendo un pulsante) dovresti usare:

[self setEditing:YES animated:YES];

invece di:

[self.tableView setEditing:YES animated:YES];

Ciò significa che la selezione multipla è abilitata solo quando la tabella è in modalità di modifica.


Questo è stato utile. Avevo impostato allowMultipleSelection nello Storyboard. Questo l'ha risolto.
Mark Suman

1
Questo ha risolto un problema che ci ha fatto impazzire. Ora capisco che "scorri per eliminare" e "eliminazione batch in modalità modifica" si escludono a vicenda e devi controllarlo quando entri in modalità modifica / leavin. Grazie mille per aver studiato questo!
fbitterlich,

18

Sotto UITableViewDataSource ti aiuterà a eliminare il colpo

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return YES if you want the specified item to be editable.
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [arrYears removeObjectAtIndex:indexPath.row];
        [tableView reloadData];
    }
}

arrYears è un NSMutableArray e quindi ricarica tableView

veloce

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

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyleDelete {
        arrYears.removeObjectAtIndex(indexPath.row)
        tableView.reloadData()
    }
}

Ma è UITableViewDataSource
HotJard

17

In iOS 8 e Swift 2.0, prova questo,

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
   // let the controller to know that able to edit tableView's row 
   return true
}

override func tableView(tableView: UITableView, commitEdittingStyle editingStyle UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)  {
   // if you want to apply with iOS 8 or earlier version you must add this function too. (just left in blank code)
}

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]?  {
   // add the action button you want to show when swiping on tableView's cell , in this case add the delete button.
   let deleteAction = UITableViewRowAction(style: .Default, title: "Delete", handler: { (action , indexPath) -> Void in

   // Your delete code here.....
   .........
   .........
   })

   // You can set its properties like normal button
   deleteAction.backgroundColor = UIColor.redColor()

   return [deleteAction]
}

Questa è una buona risposta, con questa puoi anche impostare più azioni.
Munib,

11

La risposta di Kurbz è fantastica, ma voglio lasciare questa nota e spero che questa risposta possa far risparmiare un po 'di tempo alle persone.

Occasionalmente avevo queste linee nel mio controller e rendevano la funzione di scorrimento non funzionante.

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewCellEditingStyleNone; 
}

Se usi UITableViewCellEditingStyleInserto UITableViewCellEditingStyleNonecome stile di modifica, la funzione di scorrimento non funziona. Puoi usare solo UITableViewCellEditingStyleDelete, che è lo stile predefinito.


1
Nel mio caso volevo poter scorrere per eliminare, ma poi anche spostare le mie celle. Una cella mobile ottiene anche questo pulsante "Elimina" sul lato sinistro della cella, che non si adattava al mio design e per rimuovere questo stile di modifica dovrebbe essere .none. Ho risolto questo problema con "if tableView.isEditing {return .none} else {return .delete}"

Ho salvato il mio amico axz. Grazie :)
Sourav Chandra l'

9

Swift 4

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let delete = UITableViewRowAction(style: .destructive, title: "delete") { (action, indexPath) in
        // delete item at indexPath
    tableView.deleteRows(at: [indexPath], with: .fade)

    }
    return [delete]
}

1
Ok questo fa apparire la scheda Elimina, ma non la elimina quando la premi. È necessario eliminare l'oggetto nell'origine dati e ricaricare la tabella sì?
user3069232

sì "// elimina elemento in indexPath" posiziona la logica della riga di eliminazione in base a indexPath
Lad

8

Inoltre, ciò può essere ottenuto in SWIFT usando il metodo come segue

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if (editingStyle == UITableViewCellEditingStyle.Delete){
        testArray.removeAtIndex(indexPath.row)
        goalsTableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
    }
}

8

Swift 3

Tutto quello che devi fare è abilitare queste due funzioni:

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

    return true

}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == UITableViewCellEditingStyle.delete {
        tableView.reloadData()
    }

}

7

So che è una vecchia domanda, ma la risposta di @Kurbz ne ha bisogno solo per Xcode 6.3.2 e SDK 8.3

Ho bisogno di aggiungere [tableView beginUpdates]e [tableView endUpdates](grazie a @ bay.phillips qui )

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    // Open "Transaction"
    [tableView beginUpdates];

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // your code goes here
        //add code here for when you hit delete
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
     }

    // Close "Transaction"
    [tableView endUpdates];
}

6

Quando rimuovi una cella della vista tabella, devi anche rimuovere l'oggetto array nell'indice x.

Penso che puoi rimuoverlo usando un gesto di scorrimento. La vista tabella chiamerà il delegato:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //add code here for when you hit delete
        [dataSourceArray removeObjectAtIndex:indexPath.row];
    }    
}

Dopo aver rimosso l'oggetto. Devi ricaricare l'uso di tableview. Aggiungi la seguente riga nel tuo codice:

[tableView reloadData];

successivamente, la riga è stata eliminata correttamente. E quando ricarichi la vista o aggiungi dati a DataSource l'oggetto non sarà più lì.

Per tutti gli altri è corretta la risposta di Kurbz.

Volevo solo ricordarti che la funzione di delegato non sarà sufficiente se desideri rimuovere l'oggetto dall'array DataSource.

Spero di averti aiutato.



6
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        //add code here for when you hit delete
        [dataSourceArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }    
}    

dataSourceArray è l'array da cui proviene il contenuto della cella
Rahul K Rajan

2

Swift 2.2:

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

override func tableView(tableView: UITableView,
    editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
    let delete = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "DELETE"){(UITableViewRowAction,NSIndexPath) -> Void in

    print("Your action when user pressed delete")
}
let edit = UITableViewRowAction(style: UITableViewRowActionStyle.Normal, title: "EDIT"){(UITableViewRowAction,NSIndexPath) -> Void in

    print("Your action when user pressed edit")
}
    return [delete, block]
}

2

Per Swift, basta scrivere questo codice

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            print("Delete Hit")
        }
}

Per l'obiettivo C, basta scrivere questo codice

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
       if (editingStyle == UITableViewCellEditingStyleDelete) {           
            NSLog(@"index: %@",indexPath.row);
           }
}

2

per il codice swift4, prima abilita la modifica:

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

quindi aggiungi l'azione di eliminazione al delegato di modifica:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let action = UITableViewRowAction(style: .destructive, title: "Delete") { (_, index) in
        // delete model object at the index
        self.models[index.row]
        // then delete the cell
        tableView.beginUpdates()
        tableView.deleteRows(at: [index], with: .automatic)
        tableView.endUpdates()

    }
    return [action]
}

0

Swift 4,5

Per eliminare una cella al passaggio del dito ci sono due metodi integrati di UITableView. Scrivere questo metodo nell'estensione dataView di TableView.

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let delete = deleteProperty(at: indexPath)
        return UISwipeActionsConfiguration(actions: [delete])
    }

//Declare this method in Viewcontroller Main and modify according to your need

func deleteProperty(at indexpath: IndexPath) -> UIContextualAction {
        let action = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completon) in
            self.yourArray.remove(at: indexpath) //Removing from array at selected index

            completon(true)
        action.backgroundColor = .red //cell background color
    }
        return action
    }

0

Se stai adottando fonti di dati diffuse, dovrai spostare i callback delegati in una UITableViewDiffableDataSourcesottoclasse. Per esempio:

class DataSource: UITableViewDiffableDataSource<SectionType, ItemType> {

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            if let identifierToDelete = itemIdentifier(for: indexPath) {
                var snapshot = self.snapshot()
                snapshot.deleteItems([identifierToDelete])
                apply(snapshot)
            }
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.