2015-08-31 84 views
0

我試圖在基於視圖的NSTableView中顯示非常基本的數據結構。經過幾個小時的搜索,我終於得到了大部分桌子的設置點。行數是正確的,我知道func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int)方法爲所有單元執行,因爲它在控制檯中輸出正確的數據。不幸的是,表格顯示的是默認值,而不是我的數據數組中的String在Swift中基於視圖的NSTableView不顯示內容

The table view doesn't display the correct data

下面的代碼:

ViewController.swift

import Cocoa 

class ViewController: NSViewController { 

    @IBOutlet weak var myTableView: NSTableView! 
    var files = [FilesListData]() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.setupSampleFiles() 
    } 
    override func viewDidAppear() { 
     super.viewDidAppear() 
    } 

    func setupSampleFiles() { 
     let file1 = FilesListData(file: "test.mp3", title: "test") 
     let file2 = FilesListData(file: "test2.mp3", title: "test 2") 

     self.files = [file1, file2] 
    } 
} 

extension ViewController: NSTableViewDataSource { 
    func numberOfRowsInTableView(tableView: NSTableView) -> Int { 
     return self.files.count 
    } 

    func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { 
     let cellView: NSTableCellView = tableView.makeViewWithIdentifier((tableColumn!.identifier), owner: self) as! NSTableCellView 

     let fileData = self.files[row] 
     if tableColumn!.identifier == "fileCol" { 
      cellView.textField!.stringValue = fileData.file 
     } else if tableColumn!.identifier == "titleCol" { 
      cellView.textField!.stringValue = fileData.title 
     } else { 
      cellView.textField!.stringValue = "N/A" 
     } 
     return cellView 
    } 
} 

extension ViewController: NSTableViewDelegate { 
} 

FilesListData.swift

import Foundation 

class FilesListData: NSObject { 
    var file: String 
    var title: String 

    override init() { 
     self.file = String() 
     self.title = String() 
    } 

    init(file: String, title: String) { 
     self.file = file 
     self.title = title 
    } 
} 

一些更多的注意事項:在故事板,我也創建dataSource和的插座3210添加到View Controller。我的前兩列的標識符被設置爲「fileCol」和「titleCol」。該項目編譯並運行時沒有任何錯誤或警告。以下是我的故事板的幾個截圖。

Objects tree

Identifier for the first column

回答

1

看起來你已經混了兩種不同的方法。 數據源方法tableView(_:objectValueForTableColumn:row:)用於返回數據對象,而不是單元格視圖。 代表方法tableView(_:viewForTableColumn:row:)用於返回單元格視圖,可能配置了適合列和行的數據。

所以,你可能重寫前者如:

func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { 
    let fileData = self.files[row] 
    if tableColumn!.identifier == "fileCol" { 
     return fileData.file 
    } else if tableColumn!.identifier == "titleCol" { 
     return fileData.title 
    } 

    return "N/A" 
} 

注意,它並不試圖創建或返回一個視圖。

這是第一步。表視圖將採用您從該方法返回的對象值,並將其分配給您用作單元視圖的NSTableCellViewobjectValue屬性。然而,它本身並沒有做任何事情。

有幾種不同的方法才能讓該對象的值在你的意見,實際顯示:

  • 而不是使用NSTableCellView S,每個都包含一個文本框,因爲你的意見,使用一個文本字段本身。由於NSTextField也有objectValue屬性(從NSControl繼承),因此表視圖可以在其上設置對象值,並顯示您的內容。缺點是你的單元格視圖只是一個視圖。如果你想在每個單元格中看到多個視圖,就不能使用這種方法。
  • 繼續使用NSTableCellView作爲你的單元格視圖,就像你現在正在做的那樣。將文本字段的值綁定綁定到包含NSTableCellView的關鍵路徑objectValue。這樣,當表格設置NSTableCellViewobjectValue時,它會自動傳播到文本字段。
  • 實施tableView(_:viewForTableColumn:row:)通過直接設置文本字段屬性的值來配置單元格視圖。基本上,這看起來像是你爲tableView(_:objectValueForTableColumn:row:)實施的主體。這有效地使您的執行tableView(_:objectValueForTableColumn:row:)冗餘。您需要實現它,表視圖將調用它並使用結果來設置單元格視圖的objectValue,但這對單元格視圖內的文本字段沒有影響。
  • 使用NSTableCellView的自定義子類,它將didSet屬性觀察者添加到objectValue屬性。這可以將新的價值適當地轉發給子視圖。

就我個人而言,我使用綁定方法。

另外,您應該考慮從tableView(_:objectValueForTableColumn:row:)返回整個fileData對象,而不是其某個屬性的值。所以,tableView(_:objectValueForTableColumn:row:)不會對列,只有行敏感。每個NSTableCellViewobjectValue將是相應的FilesListData實例。

然後,將調整文本字段與其封閉單元格視圖的綁定,以選擇FilesListData的相應屬性。例如,一列中的文本字段將被綁定到其包含NSTableCellView的關鍵路徑objectValue.file。在另一列中,它將使用關鍵路徑objectValue.title

如果您的單元格視圖最終變得更加複雜並且其中包含多個視圖,那麼這將特別有用。每個視圖都可以訪問FilesListData對象的任何屬性。使用目前的方法只返回單個屬性作爲單元格的對象值,那麼視圖就會停留在僅使用該值的狀態。

+0

你好肯和謝謝你的徹底答案。我想保留'NSTableCellView's,因爲正如你所提到的那樣,我將能夠在後面擴展表格的複雜性。我能夠通過實現'tableView(_:viewForTableColumn:row:)'成功顯示數據。然而,綁定方法似乎很有趣,但我不知道如何實現這一點。你提到的「價值」就是'委託'出口? N.B .:我沒有提到的一件事是我的'NSTableCellView'的'textField'有一個到它的子節點'NSTextField'的插座。 – beeb

+0

設置綁定的最簡單方法是在IB中。選擇文本字段後,選擇視圖>實用程序>顯示綁定檢查器。切換打開值綁定。對於「綁定到」彈出窗口,請選擇表格單元格視圖。對於模型關鍵路徑輸入'objectValue.file'或類似的東西。 (Xcode會顯示一個感嘆號圖標,因爲它無法驗證關鍵路徑是否有效,但是您可以忽略它。這是系統的動態性質,因爲它無法知道'objectValue'類型是什麼類型。) –

+0

精彩,這就像一個魅力!再次感謝 – beeb

相關問題