Ich versuche, einige arbeiten aber hässlich Code zu verfeinern.Swift: Gegossene TabelleCell als variable Klasse
Meine App verfügt über fünf TableViews, von denen jede eine andere Art von Daten anzeigt (mit unterschiedlichen Zellenlayouts). Da die Datentypen ähnlich sind und viele ähnliche Methoden erfordern (zum Herunterladen, Codieren usw.), habe ich eine TableViewController: UITableViewController-Klasse eingerichtet, die als Oberklasse für die fünf TableViewController-Unterklassen dient. Innerhalb dieser Oberklasse habe ich die Standardmethode "cellForRowAt", aber sie ist aufgebläht und repetitiv. Ich möchte es vereinfachen.
Mein Problem (ich denke) ist die multiple "let cell =" Anweisungen, die alle als eine andere Art von TableViewCell abhängig von den Datentypen umgewandelt werden. Zum Beispiel muss mein DataType.SCHEDULES-Datentyp eine SchedulesTableViewCell mit reuseID von "SchedulesCell" erhalten. Ich kann sie nicht alle zur selben TableViewCell-Klasse machen, da sie jeweils eigene IBOutlet-Ansichten haben.
Um die Sache hässlicher zu machen, hat jeder TableView zwei Zellprototypen, und ich muss in der Lage sein, eine ARTICLE-Zelle und eine DETAIL-Zelle für jeden Datentyp zu generieren.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// get the article and row type
let article = getArticleFor(indexPath: indexPath)
let cellType = getCellTypeFor(indexPath: indexPath)
// create either an ARTICLE row or a DETAIL row.
// (simplified for SO posting. Each "case" is actually
// 5-6 lines of nearly identical code)
switch cellType {
// for the ARTICLE cell prototype
case CellType.ARTICLE:
// get the right table cell matching the datatype
switch self.datatype {
case DataType.SCHEDULES:
let cell = tableView.dequeueReusableCell(withIdentifier: "SchedulesCell") as! SchedulesTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.LUNCH:
let cell = tableView.dequeueReusableCell(withIdentifier: "LunchCell") as! LunchTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.EVENTS:
let cell = tableView.dequeueReusableCell(withIdentifier: "EventsCell") as! EventsTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.DAILY_ANN:
let cell = tableView.dequeueReusableCell(withIdentifier: "DailyannCell") as! DailyannTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.NEWS:
let cell = tableView.dequeueReusableCell(withIdentifier: "NewsCell") as! NewsTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
}
// or for the DETAIL cell prototype
case CellType.DETAIL:
// get the right table cell matching the datatype
switch self.datatype {
case DataType.SCHEDULES:
let cell = tableView.dequeueReusableCell(withIdentifier: "SchedulesDetailsCell") as! ScheduleDetailTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.LUNCH:
let cell = tableView.dequeueReusableCell(withIdentifier: "LunchDetailsCell") as! LunchDetailsTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.EVENTS:
let cell = tableView.dequeueReusableCell(withIdentifier: "EventsDetailsCell") as! EventsDetailTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.DAILY_ANN:
let cell = tableView.dequeueReusableCell(withIdentifier: "DailyannDetailCell") as! DailyannDetailsTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
case DataType.NEWS:
let cell = tableView.dequeueReusableCell(withIdentifier: "NewsDetailCell") as! NewsDetailTableViewCell
cell.fillCellWith(article: article)
cell.otherMethod2()
cell.otherMethod3()
return cell
}
}
}
Ich hatte ursprünglich jeden „Zelle lassen =“ Fall innerhalb der eigenen Unterklassen ‚cellForRowAt‘ Methoden, aber ich wiederhole sehr ähnlichen Code in jeder Unterklasse, die dumm zu sein schien. Auf der anderen Seite hat der obige Code die Wiederholung in eine einzelne Klasse verschoben, aber die Wiederholung nicht entfernt, also ist es immer noch albern, aber an einem anderen Ort.
Ich mag das Gefühl, wenn ich ein Wörterbuch der Klassen machen könnte, so etwas wie dieses ...
let tableCellClasses = [DataType.SCHEDULES : ScheduleTableViewCell,
DataType.LUNCH : LunchTableViewCell
etc.
... dann könnte ich meine „lassen Zelle =“ machen Aussagen allgemeineren, wie ...
let cell = tableView.dequeueReusableCell(withIdentifier: identifier[dataType]) as! tableCellClasses[dataType]
aber kann nicht scheinen, einen Weg zu finden, damit es funktioniert.
Wie gesagt, es funktioniert, aber es ist hässlich. Ich arbeite in einer High School, also möchte ich, dass Studenten, die das Repo ansehen, sauberen, gut strukturierten Code sehen - also schieße ich besser als nur "es funktioniert".
Irgendwelche Vorschläge?
Wenn ich eine TableViewCell-Basisklasse erstelle, hat sie keinen Zugriff auf meine IBOutlet-Sichten in den Unterklassen. Wenn ich also meine "let cell =" - Anweisungen anrufe, wenn diese als Basisklasse umgewandelt werden, können die Basisklassenmethoden die Zellansichten der Unterklassen nicht füllen. Oder bin ich ein Missverständnis? –
Ich denke, wenn Sie die entsprechende Unterklasse für jede Prototypzelle im identify inpector festlegen, instanziiert das Storyboard es wie angefordert. Das Umwandeln in die Basisklasse "konvertiert" es nicht in eine Instanz der Basisklasse (die es in gewissem Sinne bereits ist), aber Sie können 'fillCellWith (article:)' aufrufen, ohne einen Compilerfehler zu haben. Wenn die spezifische Unterklasse die Methode überschreibt, wird die überschriebene Implementierung aufgerufen. Das Outlet-Setup sollte im Quellcode der Zellen-Unterklasse ausgeführt werden. Es handelt sich also um ein Implementierungsdetail, das von Ihrem Tabellenansicht-Controller isoliert ist. –
Und wahrscheinlich verwenden 'dequeueReusableCell (withIdentifier :, für:)' –