mac 純程式碼建立tableview

tongwei117發表於2017-05-08

iOS和Mac OS的tableview使用略有不同

Mac OS的tableView需要一個Container來包裹它,才可以滑動,而iOS的不用
Mac OS的tableview裡面多了一個概念叫做column(列),而iOS中沒有這個概念
iOS中有section的概念,可是Mac OS中沒有(NSCollectionView中有)

註釋:如果Mac開發中需求必需使用section的話,可以去研究下NSCollectionView

Mac os的tableview在datasource做檢視的時候,有兩種情況:
1、View Based TableView
2、Cell Based TableView
這兩種情況可用的delegate方法不太相同,需要注意,否則可能出現delegate方法不被呼叫的問題

@interface AppDelegate ()<NSTableViewDataSource,NSTableViewDelegate>
{
    NSScrollView *_tableContainerView;
    NSMutableArray *_dataSourceArray;

    NSTextField *_scrollTF;
    NSButton *_deleteBtn;
    NSButton *_addBtn;

    NSInteger _selectedRowNum;
}
@property (weak) IBOutlet NSWindow *window;
@property (nonatomic) NSTableView *tableView;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    //虛擬的dataSource
    _dataSourceArray = [[NSMutableArray alloc] initWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9", nil];
    _selectedRowNum = -1;

    //刪除按鈕
    _deleteBtn = [[NSButton alloc] initWithFrame:CGRectMake(415, 250, 70, 25)];
    _deleteBtn.title = @"刪除選中行";
    _deleteBtn.wantsLayer = YES;
    _deleteBtn.layer.cornerRadius = 3.0f;
    _deleteBtn.layer.borderColor = [NSColor lightGrayColor].CGColor;
    [_deleteBtn setTarget:self];
    _deleteBtn.action = @selector(deleteTheSelectedRow);
    [self.window.contentView addSubview:_deleteBtn];

    //新增按鈕
    _addBtn = [[NSButton alloc] initWithFrame:CGRectMake(415, 170, 70, 25)];
    _addBtn.title = @"上面添一行";
    _addBtn.wantsLayer = YES;
    _addBtn.layer.cornerRadius = 3.0f;
    _addBtn.layer.borderColor = [NSColor lightGrayColor].CGColor;
    [_addBtn setTarget:self];
    _addBtn.action = @selector(addRowUnderTheSelectedRow);
    [self.window.contentView addSubview:_addBtn];

    //滾動顯示的TF
    _scrollTF = [[NSTextField alloc] initWithFrame:CGRectMake(415, 90, 80, 15)];
    _scrollTF.stringValue = @"滾動 0.0";
    _scrollTF.font = [NSFont systemFontOfSize:15.0f];
    _scrollTF.textColor = [NSColor blackColor];
    _scrollTF.drawsBackground = NO;
    _scrollTF.bordered = NO;
    _scrollTF.focusRingType = NSFocusRingTypeNone;
    _scrollTF.editable = NO;
    [self.window.contentView addSubview:_scrollTF];

    //tableView
    _tableContainerView = [[NSScrollView alloc] initWithFrame:CGRectMake(0, 0, 400, 309)];
    _tableView = [[NSTableView alloc] initWithFrame:CGRectMake(0, 20,
                                                               _tableContainerView.frame.size.width-20,
                                                               _tableContainerView.frame.size.height)];
    [_tableView setBackgroundColor:[NSColor colorWithCalibratedRed:220.0/255 green:220.0/255 blue:220.0/255 alpha:1.0]];
    _tableView.focusRingType = NSFocusRingTypeNone;                             //tableview獲得焦點時的風格
    _tableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular;//行高亮的風格
    _tableView.headerView.frame = NSZeroRect;                                   //表頭
    _tableView.delegate = self;
    _tableView.dataSource = self;

    // 第一列
    NSTableColumn * column1 = [[NSTableColumn alloc] initWithIdentifier:@"firstColumn"];
    [column1 setWidth:200];
    [_tableView addTableColumn:column1];//第一列

    // 第二列
    NSTableColumn * column2 = [[NSTableColumn alloc] initWithIdentifier:@"secondColumn"];
    [column2 setWidth:200];
    [_tableView addTableColumn:column2];//第二列

    [_tableContainerView setDocumentView:_tableView];
    [_tableContainerView setDrawsBackground:NO];        //不畫背景(背景預設畫成白色)
    [_tableContainerView setHasVerticalScroller:YES];   //有垂直滾動條
    //[_tableContainer setHasHorizontalScroller:YES];   //有水平滾動條
    _tableContainerView.autohidesScrollers = YES;       //自動隱藏滾動條(滾動的時候出現)
    [self.window.contentView addSubview:_tableContainerView];

    //監測tableview滾動
    [[NSNotificationCenter defaultCenter]addObserver:self
                                            selector:@selector(tableviewDidScroll:)
                                                name:NSViewBoundsDidChangeNotification
                                              object:[[_tableView enclosingScrollView] contentView]];
}
#pragma mark - NSTableViewDataSource,NSTableViewDelegate
#pragma mark -required methods
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
    return _dataSourceArray.count;
}
//這個方法雖然不返回什麼東西,但是必須實現,不實現可能會出問題-比如行檢視顯示不出來等。(10.11貌似不實現也可以,可是10.10及以下還是不行的)
- (nullable id)tableView:(NSTableView *)tableView objectValueForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row
{
    return nil;
}
#pragma mark -other methods
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
    return 58;
}
- (nullable NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(nullable NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSString *strIdt=[tableColumn identifier];
    NSTableCellView *aView = [tableView makeViewWithIdentifier:strIdt owner:self];
    if (!aView)
        aView = [[NSTableCellView alloc]initWithFrame:CGRectMake(0, 0, tableColumn.width, 58)];
    else
        for (NSView *view in aView.subviews)[view removeFromSuperview];

    NSTextField *textField = [[NSTextField alloc] initWithFrame:CGRectMake(15, 20, 156+50, 17)];
    textField.stringValue = [NSString stringWithFormat:@"%@-ºµº-%@",tableColumn.identifier,[_dataSourceArray objectAtIndex:row]];
    textField.font = [NSFont systemFontOfSize:15.0f];
    textField.textColor = [NSColor blackColor];
    textField.drawsBackground = NO;
    textField.bordered = NO;
    textField.focusRingType = NSFocusRingTypeNone;
    textField.editable = NO;
    [aView addSubview:textField];
    return aView;
}
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row
{
//    NSLog(@"====%ld", (long)row);
    _selectedRowNum = row;
    return YES;
}

- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)tableColumn{
    NSLog(@"%@", tableColumn.dataCell);
}
#pragma mark - tableview滾動處理
-(void)tableviewDidScroll:(NSNotification *)notification
{
    NSClipView *contentView = [notification object];
    CGFloat scrollY = contentView.visibleRect.origin.y-20;//這裡減去20是因為tableHeader的20高度
    _scrollTF.stringValue = [NSString stringWithFormat:@"滾動 %.1f",scrollY];
}


#pragma mark - 刪除&&新增某一行
-(void)deleteTheSelectedRow
{
    if (_selectedRowNum == -1) {NSLog(@"請先選擇要刪除的行"); return;}
    [_tableView beginUpdates];
    [_dataSourceArray removeObjectAtIndex:_selectedRowNum];
    [_tableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:_selectedRowNum] withAnimation:NSTableViewAnimationSlideUp];
    [_tableView endUpdates];
    _selectedRowNum = -1;
}
-(void)addRowUnderTheSelectedRow
{
    if (_selectedRowNum == -1) {NSLog(@"請先選擇要哪行上面添一行"); return;}
    NSString *seletedDataObject = [_dataSourceArray objectAtIndex:_selectedRowNum];
    NSString *addObject = [NSString stringWithFormat:@"%@+",seletedDataObject];

    [_tableView beginUpdates];
    [_dataSourceArray insertObject:addObject atIndex:_selectedRowNum];
    [_tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:_selectedRowNum] withAnimation:NSTableViewAnimationSlideDown];
    [_tableView endUpdates];
    _selectedRowNum++;
}
#pragma mark -
- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}
// 選中的響應
-(void)tableViewSelectionDidChange:(nonnull NSNotification* )notification{
    self.tableView = notification.object;
    //do something
    NSLog(@"-----%ld", (long)self.tableView.selectedRow);
}

相關文章