单击更改自定义视图单元格
change custom view cell on click
我和 swift 一起工作 osx。
我有一个带有自定义单元格视图的 nstableview(一行,一列)。
在情节提要中,我有 "designed" 两个不同的行布局,带有标识符 CellLayout1 和 CellLayout2
func numberOfRows(in tableView: NSTableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let view = tblPositions.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
view.txtName.stringValue = dataArray[row]
return view
}
现在我想显示 CellLayout2,如果我点击一行
我使用这个函数来检查 selection 是否在变化:
func tableViewSelectionDidChange(_ notification: Notification) {
// ?
}
但现在我不知道如何显示 selected 行的 CellLayout2。
有谁能够帮助我? :)
更新
var selectedRow = Int()
func numberOfRows(in tableView: NSTableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
if selectedRow == row {
return 200
} else {
return 60
}
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if selectedRow == row {
let view = tableView.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
return view
}
let view = tableView.make(withIdentifier: "CellLayout2", owner: nil) as! CustomCell
return view
}
func tableViewSelectionDidChange(_ notification: Notification) {
selectedRow = tblPositions.selectedRow
tblPositions.reloadData()
//tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes)
}
这种方式近乎完美 - 但是:
布局仅在我重新加载完整 table 时才会更改。此代码没有任何效果://tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes)
。
如果我 select 一行,table视图重新加载数据,布局会改变,但 selected 行会 deselect编辑。这不应该发生。
做一个好的 MVC 应该是这样的。
- 在单元格上单击您正在更新数据模型。例如更改标志。
- 模型应该触发该更改的通知
您的控制器应该观察模型,并且当收到该项目已更改的通知时,您应该将此通知传递给 table 视图:
tableView.func reloadData(forRowIndexes: rowsToUpdate columnIndexes: colmnToUpdate)
table 视图将重新加载给定索引的单元格
- 它将再次调用
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int)
您提供与项目标志匹配的单元格。
当使用 Array
作为数据模型时,可以使用 KVO
。
从我的一些项目中,我有一个很好的例子,说明控制器的外观。它在 Objective C 中,但应该会有帮助:
static char dummy = 0;
static NSString * const kImageCellsId = @"ImageCellView";
static NSString * const kDescriptionCellId = @"DescriptionCellView";
@interface CommonImagesViewController () <NSTableViewDataSource, NSTabViewDelegate>
@property (nonatomic, strong) IBOutlet NSTableView *tableView;
@property (nonatomic, strong) CommonImagesHandler *imageHandler;
@end
@implementation CommonImagesViewController
- (void)dealloc {
[self.imageHandler removeObserver: self
forKeyPath: kCommonImagesHandlerImageCollectionKey
context: &dummy];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.imageHandler = ClientManager.getInstance.imageHandler;
[self.imageHandler addObserver: self
forKeyPath: kCommonImagesHandlerImageCollectionKey
options: (NSKeyValueObservingOptions)0
context: &dummy];
[self.tableView reloadData];
}
#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return (NSInteger)self.imageHandler.imageCollection.count;
}
#pragma mark - NSTabViewDelegate
- (nullable NSView *)tableView: (NSTableView *)tableView
viewForTableColumn: (nullable NSTableColumn *)tableColumn
row: (NSInteger)row
{
ImageData *item = self.imageHandler.imageCollection[(NSUInteger)row];
if (tableColumn == tableView.tableColumns[0]) {
NSTableCellView *cell = (NSTableCellView *)[self.tableView makeViewWithIdentifier: kImageCellsId owner: nil];
cell.imageView.image = item.image;
cell.textField.stringValue = item.userDesc;
return cell;
}
return nil;
}
#pragma mark - actions
- (IBAction)deleteAllEntries:(id)sender
{
[self.imageHandler clearImageCollection];
}
- (IBAction)deleteSelected:(id)sender
{
NSIndexSet *indexes = self.tableView.selectedRowIndexes;
[self.imageHandler removeImageCollectionAtIndexes: indexes];
}
- (IBAction)viewImage:(id)sender
{
// TODO:
}
#pragma mark - KVO
- (void)observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
if (context == &dummy) {
if (self.imageHandler == object && [keyPath isEqualToString: kCommonImagesHandlerImageCollectionKey]) {
NSIndexSet *indexSet = change[NSKeyValueChangeIndexesKey];
if (indexSet.count == 0) {
return;
}
NSKeyValueChange changeType = (NSKeyValueChange)[change[NSKeyValueChangeKindKey] integerValue];
switch (changeType) {
case NSKeyValueChangeSetting:
[self.tableView reloadDataForRowIndexes: indexSet
columnIndexes: [NSIndexSet indexSetWithIndex: 0]];
break;
case NSKeyValueChangeInsertion:
[self.tableView insertRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideLeft];
break;
case NSKeyValueChangeRemoval:
[self.tableView removeRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideRight];
break;
case NSKeyValueChangeReplacement:
[self.tableView reloadData];
break;
}
}
} else {
[super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context];
}
}
@end
其中 self.imageHandler
指向我的数据模型,其中包含完全支持 KVO 的数组。
我和 swift 一起工作 osx。 我有一个带有自定义单元格视图的 nstableview(一行,一列)。 在情节提要中,我有 "designed" 两个不同的行布局,带有标识符 CellLayout1 和 CellLayout2
func numberOfRows(in tableView: NSTableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let view = tblPositions.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
view.txtName.stringValue = dataArray[row]
return view
}
现在我想显示 CellLayout2,如果我点击一行 我使用这个函数来检查 selection 是否在变化:
func tableViewSelectionDidChange(_ notification: Notification) {
// ?
}
但现在我不知道如何显示 selected 行的 CellLayout2。 有谁能够帮助我? :)
更新
var selectedRow = Int()
func numberOfRows(in tableView: NSTableView) -> Int {
return dataArray.count
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
if selectedRow == row {
return 200
} else {
return 60
}
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if selectedRow == row {
let view = tableView.make(withIdentifier: "CellLayout1", owner: nil) as! CustomCell
return view
}
let view = tableView.make(withIdentifier: "CellLayout2", owner: nil) as! CustomCell
return view
}
func tableViewSelectionDidChange(_ notification: Notification) {
selectedRow = tblPositions.selectedRow
tblPositions.reloadData()
//tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes)
}
这种方式近乎完美 - 但是:
布局仅在我重新加载完整 table 时才会更改。此代码没有任何效果:
//tblPositions.reloadData(forRowIndexes: tblPositions.selectedRowIndexes, columnIndexes: tblPositions.selectedColumnIndexes)
。如果我 select 一行,table视图重新加载数据,布局会改变,但 selected 行会 deselect编辑。这不应该发生。
做一个好的 MVC 应该是这样的。
- 在单元格上单击您正在更新数据模型。例如更改标志。
- 模型应该触发该更改的通知
您的控制器应该观察模型,并且当收到该项目已更改的通知时,您应该将此通知传递给 table 视图:
tableView.func reloadData(forRowIndexes: rowsToUpdate columnIndexes: colmnToUpdate)
table 视图将重新加载给定索引的单元格
- 它将再次调用
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int)
您提供与项目标志匹配的单元格。
当使用 Array
作为数据模型时,可以使用 KVO
。
从我的一些项目中,我有一个很好的例子,说明控制器的外观。它在 Objective C 中,但应该会有帮助:
static char dummy = 0;
static NSString * const kImageCellsId = @"ImageCellView";
static NSString * const kDescriptionCellId = @"DescriptionCellView";
@interface CommonImagesViewController () <NSTableViewDataSource, NSTabViewDelegate>
@property (nonatomic, strong) IBOutlet NSTableView *tableView;
@property (nonatomic, strong) CommonImagesHandler *imageHandler;
@end
@implementation CommonImagesViewController
- (void)dealloc {
[self.imageHandler removeObserver: self
forKeyPath: kCommonImagesHandlerImageCollectionKey
context: &dummy];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.imageHandler = ClientManager.getInstance.imageHandler;
[self.imageHandler addObserver: self
forKeyPath: kCommonImagesHandlerImageCollectionKey
options: (NSKeyValueObservingOptions)0
context: &dummy];
[self.tableView reloadData];
}
#pragma mark - NSTableViewDataSource
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return (NSInteger)self.imageHandler.imageCollection.count;
}
#pragma mark - NSTabViewDelegate
- (nullable NSView *)tableView: (NSTableView *)tableView
viewForTableColumn: (nullable NSTableColumn *)tableColumn
row: (NSInteger)row
{
ImageData *item = self.imageHandler.imageCollection[(NSUInteger)row];
if (tableColumn == tableView.tableColumns[0]) {
NSTableCellView *cell = (NSTableCellView *)[self.tableView makeViewWithIdentifier: kImageCellsId owner: nil];
cell.imageView.image = item.image;
cell.textField.stringValue = item.userDesc;
return cell;
}
return nil;
}
#pragma mark - actions
- (IBAction)deleteAllEntries:(id)sender
{
[self.imageHandler clearImageCollection];
}
- (IBAction)deleteSelected:(id)sender
{
NSIndexSet *indexes = self.tableView.selectedRowIndexes;
[self.imageHandler removeImageCollectionAtIndexes: indexes];
}
- (IBAction)viewImage:(id)sender
{
// TODO:
}
#pragma mark - KVO
- (void)observeValueForKeyPath: (NSString *)keyPath
ofObject: (id)object
change: (NSDictionary *)change
context: (void *)context
{
if (context == &dummy) {
if (self.imageHandler == object && [keyPath isEqualToString: kCommonImagesHandlerImageCollectionKey]) {
NSIndexSet *indexSet = change[NSKeyValueChangeIndexesKey];
if (indexSet.count == 0) {
return;
}
NSKeyValueChange changeType = (NSKeyValueChange)[change[NSKeyValueChangeKindKey] integerValue];
switch (changeType) {
case NSKeyValueChangeSetting:
[self.tableView reloadDataForRowIndexes: indexSet
columnIndexes: [NSIndexSet indexSetWithIndex: 0]];
break;
case NSKeyValueChangeInsertion:
[self.tableView insertRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideLeft];
break;
case NSKeyValueChangeRemoval:
[self.tableView removeRowsAtIndexes: indexSet withAnimation: NSTableViewAnimationSlideRight];
break;
case NSKeyValueChangeReplacement:
[self.tableView reloadData];
break;
}
}
} else {
[super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context];
}
}
@end
其中 self.imageHandler
指向我的数据模型,其中包含完全支持 KVO 的数组。