2014-01-17 33 views
5

我試圖將一個iOS應用程序移植到Mac上,並且在轉換過程中遇到了一些問題。其中之一是NSTableView的定製。 NSCell,NSTableRowView和定製NSView基於NSTableview究竟有什麼區別?我最初以基於NSTableView的觀點開始,但我很快注意到我必須自己處理選擇。我無法解決這個問題,所以我繼續使用NSTableRowView,奇怪的是,它並沒有將我的自定義NSTableRowView的初始化程序。基於查看的NSTableView選擇突出顯示

我基本上只想自定義表格視圖單元格與自定義內容,這是可選的。什麼是最好的方式來做到這一點?

在iOS上,我只是子類UITableViewCell並設置其selectedView屬性。在Mac上,這似乎比這更復雜。

回答

16

我剛剛發現(在側邊欄中)這個問題,建議子類NSTableRowView。我之前已經做到了,但沒有奏效。我已經試了一次,相當令人驚訝現在的工作......

Handling custom selection style in view based NSTableView

然而,這個答案不是非常豐富,所以我會盡量覆蓋什麼,我爲了讓已經做了這項工作。

首先,我實現了下面的NSTableView委託方法並返回nil!

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{ 

    return nil; 

} 

爲了使用基於視圖(我猜NSTableViewRow被認爲是一個視圖基於表,以及...),你必須實現此方法表。我不太確定我可能做錯了什麼,但是如果沒有這種方法,我的細胞就不會顯示!

確保不讓NSTableView的處理任何選擇通過設置該屬性:

yourNSTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleNone; 

好了,現在我們要建立我們的細胞具有以下的委託方法:

-(NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row{ 

    static NSString *cellID = @"cell_identifier"; 

    //use this if you want to reuse the cells 
    CustomTableRowView *result = [tableView makeViewWithIdentifier:cellID owner:self]; 

    if (result == nil) { 

     result = [[CustomTableRowView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, 80)]; 
     result.identifier = cellID; 

    } 

    result.data = [tableData objectAtIndex:row]; 

    // Return the result 
    return result; 

} 

好了,所以現在繼承NSTableRowView和實現/重寫以下兩種方法:

首先,我們必須覆蓋setSelected:我n爲了使單元格在選中時重繪其背景。所以在這裏,它是:

-(void)setSelected:(BOOL)selected{ 

    [super setSelected:selected]; 
    [self setNeedsDisplay:YES]; 

} 

正如前面提到的,我們稱之爲setNeedsDisplay:爲了使細胞重繪其背景。

最後,繪製代碼。覆蓋的方法drawBackgroundInRect:這樣的:

-(void)drawBackgroundInRect:(NSRect)dirtyRect{ 
    if (!self.selected) { 
     [[NSColor clearColor] set]; 
    } else { 
     [someColor set]; 
    } 
    NSRectFill(dirtyRect); 
} 
+1

我發現我並不需要第一位,但其他人幫助+1。謝謝。 – lateAtNight

+0

@lateAtNight很高興幫助:) –

+0

萬一它可以幫助其他人,我試圖在10.9上使用Swift來做到這一點,並獲得CGContextRef有點不同。看到這個答案尋求幫助:http://stackoverflow.com/a/24056236/2708274 – Matt

2

使用下面的代碼響應NSTableViewDelegate協議tableViewSelectionDidChange:

獲取NSTableRowView對於選擇的行,並呼籲setEmphasized它的方法。當setEmphasized設置爲YES時,您會看到藍色突出顯示,否則顯示灰色突出顯示。

-(void)tableViewSelectionDidChange:(NSNotification *)aNotification { 

    NSInteger selectedRow = [myTableView selectedRow]; 
    NSTableRowView *myRowView = [myTableView rowViewAtRow:selectedRow makeIfNecessary:NO]; 
    [myRowView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleRegular]; 
    [myRowView setEmphasized:NO]; 
} 

並避免藍色然後灰色組跳舞效果

[_tableView setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone]; 
+0

如果單擊其他應用程序而不是跳回到此應用程序,選定的行將再次變爲藍色。 – Jacky

2

the_critic在夫特溶液:(帶的XCode 7素β3測試,夫特2.0)

class CustomTableRowView: NSTableRowView { 

    override var selected: Bool { 
     willSet(newValue) { 
      super.selected = newValue; 
      needsDisplay = true 
     } 
    } 

    override func drawBackgroundInRect(dirtyRect: NSRect) { 
     let context: CGContextRef = NSGraphicsContext.currentContext()!.CGContext 

     if !self.selected { 
      CGContextSetFillColorWithColor(context, NSColor.clearColor().CGColor) 
     } else { 
      CGContextSetFillColorWithColor(context, NSColor.redColor().CGColor) 
     } 

     CGContextFillRect(context, dirtyRect) 
    } 

} 

的ViewController:

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource { 

    // [...] 

    func tableView(tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { 
     guard let rowView = tableView.makeViewWithIdentifier("RowView", owner: nil) as! CustomTableRowView? else { 
      let rowView = CustomTableRowView() 
      rowView.identifier = "RowView" 
      return rowView 
     } 

     return rowView 
    } 

}