2016-07-28 22 views
0

Ich möchte dem NSTableViewDataSource-Protokoll eine Methode mit einem Standardwert hinzufügen. Aber wenn ich das tue, wird der Standardwert immer aufgerufen, selbst wenn die Methode in der tatsächlichen Datenquelle definiert ist. Speziell:Erweitern des NSTableViewDataSource-Protokolls mit einer Standardmethode

Ich habe eine einspaltige NSTableView, die verschiedene Datenquellen zu unterschiedlichen Zeiten übernehmen kann. In einem Fall möchte ich, dass die Datenquelle nicht nur die angezeigten Werte bereitstellen kann, sondern auch die Hintergrundfarben der Zeilen in der Tabelle. In den anderen Fällen kann die Tabelle eine einzelne Farbe haben. Meine Idee war es, zuerst das NSTableViewDataSource Protokoll zu erweitern:

extension NSTableViewDataSource 
    { 
    func tableView (tableView: NSTableView, colorIndexForRow row: Int) -> Int 
     { 
     return 0 
     } 
    } 

dann in der Tabelle Delegierten ich dies gesagt:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int) 
    { 
    let colorIndex = tableView.dataSource()!.tableView(tableView, colorIndexForRow: row) 
    rowView.backgroundColor = rowColors[colorIndex] 
    } 

(rowColors ist nur ein Array von NSColor Objekte, sechs für experimentelle Zwecke.)

Schließlich sieht meine experimentellen Datenquelle wie folgt aus:

public func numberOfRowsInTableView (tableView: NSTableView) -> Int 
    { 
    return 100 
    } 

public func tableView (tableView: NSTableView, objectValueForTableColumn column: NSTableColumn?, row: Int) -> AnyObject? 
    { 
    return String(format: "This is row %3i", row) 
    } 

public func tableView (tableView: NSTableView, colorIndexForRow row: Int) -> Int 
    { 
    return row % 6  
    } 

Ich rechnete damit, einen Tisch zu schaffen, in dem die Reihen in einem rotierenden Zyklus von sechs Farben waren. Was ich tatsächlich bekomme, ist eine Tabelle in der Farbe von rowColors [0]. Der Standardwert für meine colorIndexForRow-Methode wird immer aufgerufen, obwohl ich die Methode in meiner Datenquelle bereitstelle. Meine Lektüre der Swift-Dokumentation ist, dass der Standard in einer Protokollerweiterung nur dann aufgerufen werden soll, wenn eine tatsächliche Methode nicht vorhanden ist. Kann mir jemand sagen, was ich falsch mache?

Antwort

1

Der Grund ist, weil Protokollerweiterung doesn't support class polymorphism.

Sie können Ihre Funktion umschreiben als:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int) 
{ 
    let colorIndex = self.tableView(tableView, colorIndexForRow: row) 
    rowView.backgroundColor = rowColors[colorIndex] 
} 
+0

Ummm ... Wow? Ich denke, Sie haben meine Frage beantwortet, aber geben Sie mir ein oder zwei Tage, um den Hinweis zu verstehen, den Sie gegeben haben. In der Zwischenzeit konnte ich Ihre vorgeschlagene Funktion nicht funktionieren lassen, wahrscheinlich weil ich nicht betont habe, dass ich den Tischdelegierten möglichst von der Datenquelle trennen möchte. Diese Funktion befindet sich im Delegaten und self.tableView ist dort nicht verfügbar. Ich werde darüber nachdenken, Dinge neu zu arrangieren, aber jetzt bin ich mir nicht sicher, ob das Protokoll erweitert werden soll. –

+0

Nicht-Polymorphismus bedeutet, dass Sie bei der Definition einer Funktion an dieser ursprünglichen Definition festhalten müssen. Klassen, die eine neue Implementierung für das 'tableView (, colorForRowIndex:) 'bereitstellen, können das nicht ersetzen. Deshalb hat es immer 0 zurückgegeben - so ist es ursprünglich definiert. –

+0

Danke für die Hilfe. Ich habe eine endgültige Antwort gepostet, die für mich zu funktionieren scheint, aber ich habe dir die grüne Flagge gegeben und dafür, dass du mich auf den richtigen Weg gebracht hast. Ich hoffe, das entspricht dem StackOverflow-Protokoll. –

0

Ich habe beschlossen, einen anderen Weg zu nehmen: meine einfache One-Funktion Voraussetzung rechtfertigt nicht mit statischen vs dynamischen Dispatch Fragen. Statt erstreckt NSTableViewDataSource, ich habe ein vererbte Protokoll definiert:

public protocol  ColorTableViewDataSource: NSTableViewDataSource 
    { 
    func tableView (tableView: NSTableView, colorIndexForRow row: Int) -> Int 
    } 

Und dann meine Delegatfunktion Tests für Konformität:

public func tableView (tableView: NSTableView, didAddRowView rowView: NSTableRowView, forRow row: Int) 
    { 
    if let dataSource = tableView.dataSource() as? ColorTableViewDataSource 
     { 
     rowView.backgroundColor = rowColors[dataSource.tableView(tableView, colorIndexForRow: row)] 
     } 
    } 

Meine Datenquelle Funktionen überhaupt nicht ändern. Ich deklariere das Datenquellenobjekt nur in Übereinstimmung mit dem neuen Protokoll, wenn ich farbige Zeilen möchte. Es scheint genau das zu tun, was ich will.