2014-10-27 11 views
13

Sono un debuttante alla programmazione Swift e iOS, quindi dovrai perdonare la domanda forse semplice.Aggiunta di sezioni, separate da date, a UITableView in Swift

Ho creato una tabellaView che visualizza il contenuto di un array (stringhe) con la semplice pressione di un pulsante. Ora, mi piacerebbe "raggruppare" queste stringhe nelle sezioni tableView, ordinate per data.

In dettaglio: quando l'utente tocca il pulsante, la stringa deve essere inserita nell'indice 0 dell'array e visualizzata in una sezione con un'intestazione della data odierna. Se ci sono valori più vecchi della data odierna nella matrice, questi dovrebbero essere visualizzati in una sezione separata per quella data. Ogni sezione dovrebbe corrispondere a un giorno di 24 ore e visualizzare tutte le stringhe aggiunte durante quel giorno.

Ecco alcuni esempi di codice di quello che ho ottenuto finora:

var testArray[String]() 
var sectionsInTable[String]() 

@IBOutlet weak var testTable: UITableView! 

@IBAction func saveButton(sender: AnyObject) { 

testArray.insert("\(strTest)", atIndex: 0) 
testTable.reloaddata() 

} 

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 

    return sectionsInTable.count 

} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 

    return testArray.count 

} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") 

    cell.textLabel.text = String(testArray[indexPath.row])   

    return cell 
} 

io davvero non so come gestire la parte sezioni. Spero che qualcuno possa indicarmi la giusta direzione. Grazie!

risposta

17

Lo farei di solito con Core Data e NSFetchedResultsController poiché ha metodi incorporati per ottenere sezioni.

Tuttavia, risponderò alla domanda senza utilizzare Core Data. Il codice è un po 'più incasinato, ma qui andiamo ...

Per prima cosa, devi creare un oggetto che memorizzerà sia la data che il testo. Il testArray sarà una matrice di questi oggetti, anziché una matrice di stringhe. Ad esempio:

class DateTextItem: NSObject { 
    var text: String = "" 
    var insertDate: NSDate = NSDate()  
} 

var testArray = [DateTextItem]() 

Quindi quando viene colpito il saveButton, creeremo e aggiungeremo l'oggetto DateTextItem. Aggiungiamo anche la data alle sezioniIntable se non esiste già.

@IBAction func saveButton(sender: AnyObject) { 
    let newItem = DateTextItem() 
    newItem.text = "Test \(testArray.count)" 

    // this is for development only 
    // increment the date after 2 records so we can test grouping by date 
    if testArray.count >= (testArray.count/2) { 
     let incrementDate = NSTimeInterval(86400*(testArray.count/2)) 
     newItem.insertDate = NSDate(timeIntervalSinceNow:incrementDate) 
    } 

    testArray.append(newItem) 

    // this next bit will create a date string and check if it's in the sectionInTable 
    let df = NSDateFormatter() 
    df.dateFormat = "MM/dd/yyyy" 
    let dateString = df.stringFromDate(newItem.insertDate) 

    // create sections NSSet so we can use 'containsObject' 
    let sections: NSSet = NSSet(array: sectionsInTable) 

    // if sectionsInTable doesn't contain the dateString, then add it 
    if !sections.containsObject(dateString) { 
     sectionsInTable.append(dateString) 
    } 

    self.tableView.reloadData() 
} 

Successivamente, ho creato una funzione per ottenere gli elementi in una sezione poiché ne abbiamo bisogno in un paio di posti.

func getSectionItems(section: Int) -> [DateTextItem] { 
    var sectionItems = [DateTextItem]() 

    // loop through the testArray to get the items for this sections's date 
    for item in testArray { 
     let dateTextItem = item as DateTextItem 
     let df = NSDateFormatter() 
     df.dateFormat = "MM/dd/yyyy" 
     let dateString = df.stringFromDate(dateTextItem.insertDate) 

     // if the item's date equals the section's date then add it 
     if dateString == sectionsInTable[section] as NSString { 
      sectionItems.append(dateTextItem) 
     } 
    } 

    return sectionItems 
} 

Infine, qui è quello che i metodi di origine Table View dati sembrano

// MARK: - Table view data source 
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return sectionsInTable.count 
} 

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return self.getSectionItems(section).count 
} 

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    // Configure the cell... 
    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") 

    // get the items in this section 
    let sectionItems = self.getSectionItems(indexPath.section) 
    // get the item for the row in this section 
    let dateTextItem = sectionItems[indexPath.row] 

    cell.textLabel.text = dateTextItem.text 

    return cell 
} 

// print the date as the section header title 
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
    return sectionsInTable[section] 
} 
+0

Grazie mille! Lo proveremo subito e ti faremo sapere come funziona. – maxpetter

+0

Ogni volta che la tabella scorre, il ciclo funziona e l'array viene inizializzato. Non sono sicuro che sia un'ottima soluzione. È necessario preparare la lista con gli oggetti una volta e quindi usarla. –

0

si deve fare una matrice per ogni giorno (chiamato dayArray [] per esempio) e aggiungerlo al sectionInTable [] e fare qualcosa di simile:

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 

    return sectionsInTable.count 

} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 

    return sectionsInTable.objectAtIndex(section).count 

} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") 

    cell.textLabel.text = String(sectionInTable.objectAtIndex(indexPath.section).objectAtIndex(indexPath.row))   

    return cell 
} 

Scusate se ho fatto degli errori, io sono non ho familiarità con swift ma penso che l'idea possa aiutare.

+0

dove si trova il metodo per aggiungere il titolo nella sezione – SARATH

17

avevo bisogno di qualcosa di simile, e mentre Ron Fessler 's soluzione funziona, quando c'è un sacco di sezioni/righe, ci è voluto molto tempo prima che la tabella caricasse i dati, e anche dopo non era molto reattivo. Il problema principale lì penso sia la funzione getSectionItems poiché passerà sempre attraverso tutti gli elementi ...

La mia soluzione: metodi dataSource

struct TableItem { 
    let title: String 
    let creationDate: NSDate 
} 

var sections = Dictionary<String, Array<TableItem>>() 
var sortedSections = [String]() 

@IBAction func saveButton(sender: AnyObject) { 

    let date:String = "your date in string..." 

    //if we don't have section for particular date, create new one, otherwise we'll just add item to existing section 
    if self.sections.indexForKey(date) == nil { 
     self.sections[date] = [TableItem(title: name, creationDate: date)] 
    } 
    else { 
     self.sections[date]!.append(TableItem(title: name, creationDate: date)) 
    } 

    //we are storing our sections in dictionary, so we need to sort it 
    self.sortedSections = self.sections.keys.array.sorted(>) 
    self.tableView.reloadData() 
} 

tableView:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return sections.count 
} 

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return sections[sortedSections[section]]!.count 
} 

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    var cell = tableView.dequeueReusableCellWithIdentifier("Cell")   

    let tableSection = sections[sortedSections[indexPath.section]] 
    let tableItem = tableSection![indexPath.row] 

    cell.titleLabel?.text = tableItem.title 

    return cell 
} 

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 
    return sortedSections[section] 
} 
+0

Questa è una semplice soluzione semplice da implementare su un TableView esistente. Grazie molto. – tonyedwardspz

+0

Continuo a ricevere un errore atal: Indice fuori intervallo quando utilizzo [sezione] in delegato di tabelview? – Skovie

+0

@Skovie verifica che 'section' sia effettivamente entro l'intervallo di' sortedSections' prima di 'return'. Ad es .: 'se sezione