Mac开发:NSTableView教程

本文是一篇关于OS X应用程序开发的教程,详细介绍了如何使用NSTableView创建一个功能丰富的文件查看器。从创建和约束表格视图,到理解其复杂的视图层次结构,再到实现数据源和委托方法,展示文件信息,以及处理用户交互如选择和双击响应。教程还涵盖了排序功能的实现,使读者能够掌握使用NSTableView组织和呈现数据的技巧。
摘要由CSDN通过智能技术生成

TableView是OS X应用程序中一个最常用的控件。

例如邮件的消息列表和聚光灯下的搜索结果。


在本教程中,您将使用一个TableView创建一个函数文件查看器。


开始

你有一个空白的画布,您将创建一个很酷的文件查看器。

starter应用程序已经有了一些功能需要通过本教程。

与应用程序打开,选择File/Open……(Command+O快捷键)。


从弹出的新窗口中,选择任何你想要的文件夹,点击打开按钮。

你会看到在Xcode的控制台:

代表对象:file:///Users/tutorials/FileViewer/FileViewer/

这个消息显示所选文件夹的路径和起动器项目中的代码将该URL传递给视图控制器。


如果你好奇,想了解更多关于如何实现,去哪里看:

Directory.swift:包含目录结构的实现读取一个目录的内容。

WindowController.swift:包含的代码给你文件夹选择面板和传递所选目录ViewController。

ViewController.swift:包含ViewController的实现类,今天就是你会花一些时间。


您将创建的表视图,显示文件列表。


创建表视图

打开Main.storyboard的项目导航器。

选择视图控制器现场放一个表格视图的对象库视图。




接下来,您需要添加一些约束。

单击销按钮在工具栏自动布局。

在出现的弹出,设置约束条件如下:

Top, Leading 和 Trailing:0 

Bottom: 22确保选择视图约束的选项菜单。


点击三角解决自动布局问题按钮的自动布局工具栏,在选择的视图部分点击 Update Frames.


你刚刚抢占画布中的任何自动布局警告通过更新视图的框架来匹配他们的约束。



花点时间看一看一个新创建的表视图的结构。

你们可能从它的名字,它遵循典型的表结构:

它是由行和列组成的

每一行代表一个单一的项目集合中的数据模型

每一列显示模型的特定属性

每一列也可以有标题行

标题行中描述的数据列


如果您熟悉UITableView iOS,你触犯熟悉的水域,但他们更深在OS x。

事实上,你可能会惊讶于个人用户界面对象的数量构成一个NSTableView对象层次结构。


NSTableView是一个老比UITableView和更复杂的控制,这是一个不同的用户界面模式,具体地说,用户鼠标或触摸板。

UITableView的主要区别在于,你有多个列的可能性和一个头,可用于与表格视图,例如,排序和选择。

在一起,分别NSScrollView和NSClipView滚动和剪辑NSTableView的内容。

有两个NSScroller对象——一个垂直和水平滚动桌子对面。

也有一些列的对象。一个NSTableView列,这些列标题与标题。

重要的是要注意,用户可以调整和重新排序的列,但你有权利删除这种能力通过将其默认设置为禁用。

NSTableView解剖

在界面构建器,您看到了表视图的视图层次的复杂性。

多个类配合建立表结构,通常最终会看起来像这样:



这些是NSTableView的关键部分

Header View:标题的观点是NSTableHeaderView的实例。

它负责绘制标题在表的顶部。如果你需要显示一个自定义标题,您可以使用自己的头子类。


Row View:视图显示行相关的视觉属性表中的每一行视图中,选择突出显示。表显示在每一行都有自己的行视图的实例。

一个重要的区别是,行不代表你的数据;细胞的责任。

它只处理视觉属性选择颜色或分隔符。您可以创建新行子类风格你的表视图不同。


Cell Views:细胞可以说是最重要的对象在一个表格视图。在一个行和列的交叉点,你找到一个细胞。

每一个是一个NSView或NSTableCellView子类,它的责任是显示实际的数据。

你猜怎么着?您可以创建自定义视图类来显示细胞无论你想要的内容。


Column:列NSTableViewColumn所代表的类,它负责管理列的宽度和行为,如调整和重新定位。

这门课不是一个观点,而是一个控制器类。

你使用它来指定列应该如何表现,但你不能控制的视觉风格因为标题的列,行和单元的观点有东西覆盖。


注意:有两种NSTableView模式。

第一种是基于单元的表视图称为NSCell。

就像一个NSView,但年长的轻巧。

它来自早期的计算时所需的桌面优化为了画控制以最小的开销。


苹果推荐使用基于表视图,但你会看到NSCell在许多AppKit控制的,所以值得知道它是什么,它是从哪里来的。

你可以阅读更多关于NSCell苹果Control and Cell Programming Topics


好,现在这是一个很好的小慢跑到表视图结构,后面的基本理论,现在你得到这一切,是时候回到Xcode,得到你自己的表格视图。


玩表视图中的列

默认情况下,界面构建器创建了一个两列表格视图,但是你需要三列显示名称,日期和文件大小的信息。

回到Main.storyboard。

选择表格视图的视图控制器的场景。

确保您选择表视图,而不是滚动视图,其中包含它。




打开属性检查器。列的数量更改为3。

是这么简单!你的表视图现在三列。

接下来,检查多个复选框选择部分,因为你要选择多个文件。

还要检查交替行突出显示部分。

当启用,这告诉表格视图使用交替行颜色的背景,就像仪。


重命名列标题更具描述性的文本。选择视图控制器中的第一列的场景。


打开属性检查器,改变列标题名称。


重复操作的第二和第三列,分别改变标题修改日期和大小。


注意:有一个替代方法改变列的标题。

你可以直接双击标题表视图可编辑。

两种方法结果完全相同,所以您选择哪个方法。


构建和运行。这是你应该看到:


改变信息是如何表示的

在其当前状态表视图有三列,每个都包含一个细胞视图显示一个文本字段中的文本。

但是有点乏味,所以香料起来,旁边的图标文件的文件名。你这个小升级后表看起来干净了很多。

你需要更换电池的观点与一个新的细胞类型,第一列包含一个图像和一个文本字段。

你很幸运因为界面构建器内置的这种类型的细胞。

选择Name列表格单元的观点并删除它。



打开对象库,拖拽一个图像和文本表细胞视图的第一列表格视图或视图控制器场景树,略低于表视图列的名称。


现在你鞭打东西成型!


指定的标识符


每个细胞都需要分配一个标识符。

否则,你将无法创建一个对应于一个特定的细胞视图列当你编码。

在第一列选择细胞视图,NameCellID检查员改变身份标识符。



重复这个过程在第二和第三列单元格的观点,分别命名标识符DateCellID和SizeCellID。


注意:有两种方法,你可以使用数据源填充tableview-either和委托协议在这个OS X NSTableView教程中,您将看到或通过可可绑定。

当你开始一个项目确保您选择这两种方法。

将来我们会有教程网站上封面使用可可绑定


目前表视图一无所知的数据需要显示或如何显示它,但它确实需要捆绑在一起!所以,你将实现这两个协议提供信息:

NSTableViewDataSource:告诉表格视图需要代表多少行。

NSTableViewDelegate:提供的视图单元格将显示为一个特定的行和列。


可视化过程表视图之间的合作,委托和数据来源:

表视图调用数据源方法numberOfRowsInTableView(_:)返回表将显示的行数。

表视图调用委托方法tableView(_:viewForTableColumn:行:)每一行和列。

委托创建视图的位置,使用适当的数据填充它,然后返回表视图。

这两种方法都必须实现为了显示你的表视图中的数据。

打开助理编辑,从表视图到control - drag ViewController类实现插入一个出口。


确保NSTableView类型和连接插座。出口表视图名称。


现在您可以参考表格视图代码中使用这个出口。

实现所需的数据源方法ViewController ViewController.swift最后通过添加此代码:

<span style="font-size:18px;">extension ViewController : NSTableViewDataSource {
  func numberOfRowsInTableView(tableView: NSTableView) -> Int {
    return directoryItems?.count ?? 0
  }
}</span>

这将创建一个扩展符合numberOfRowsInTableView NSTableViewDataSource协议和实现所需的方法(_:)返回目录中的文件数量,directoryItems数组的大小。

现在你需要实现委托。添加以下扩展ViewController.swift结束时:

<span style="font-size:18px;">extension ViewController : NSTableViewDelegate {
  func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
 
    var image:NSImage?
    var text:String = ""
    var cellIdentifier: String = ""
 
    // 1
    guard let item = directoryItems?[row] else {
      return nil
    }
 
    // 2
    if tableColumn == tableView.tableColumns[0] {
      image = item.icon
      text = item.name
      cellIdentifier = "NameCellID"
    } else if tableColumn == tableView.tableColumns[1] {
      text = item.date.description
      cellIdentifier = "DateCellID"
    } else if tableColumn == tableView.tableColumns[2] {
      text = item.isFolder ? "--" : sizeFormatter.stringFromByteCount(item.size)
      cellIdentifier = "SizeCellID"
    }
 
    // 3
    if let cell = tableView.makeViewWithIdentifier(cellIdentifier, owner: nil) as? NSTableCellView {
      cell.textField?.stringValue = text
      cell.imageView?.image = image ?? nil
      return cell
    }
    return nil
  }
}</span>

这段代码声明了一个扩展,它符合NSTableViewDelegate协议和实现tableView方法(_:viewForTableColumn:行)。

然后调用每个行和列的表格视图得到适当的细胞。

有很多的方法,这是一个循序渐进的崩溃。

如果没有数据显示,它没有返回任何细胞。

基于细胞的列将显示(名称、日期或大小),它集细胞标识符,文本和图像。

它被细胞视图通过调用makeViewWithIdentifier(_:所有者)。

这个方法创建或重用一个细胞与标识符。

然后它填补它与前面步骤中提供的信息并返回它。

接下来,添加此代码在viewDidLoad()方法:

<span style="font-size:18px;">tableView.setDelegate(self)
tableView.setDataSource(self)</span>

你在这里告诉其数据源的表视图将视图控制器,setDelegate(_:)和setDataSource(_:)将调用其方法。


最后一步是告诉表格视图刷新数据时,选择一个新的目录。

首先,这种方法添加到ViewController实现:

<span style="font-size:18px;">func reloadFileList() {
  directoryItems = directory?.contentsOrderedBy(sortOrder, ascending: sortAscending)
  tableView.reloadData()
}</span>

这个helper方法刷新文件列表。

首先,它调用目录方法contentsOrderedBy(_:提升),并返回一个数组排序的目录文件。然后它调用表视图方法reloadData()来告诉它刷新。

请注意,您只需要选择一个新目录时调用这个方法。

去representedObject观察者didSet,取代这行代码:

<span style="font-size:18px;">print("Represented object: \(url)")</span>

用这个:

<span style="font-size:18px;">directory = Directory(folderURL: url)
reloadFileList()</span>

您刚刚创建的实例目录指向文件夹的URL,它调用reloadFileList()方法来刷新表格视图数据。

构建和运行。

使用菜单File\Open File… or the Command+O快捷键,看奇迹发生!现在桌子上满是刚才选中的文件夹的内容。



不错的工作!

但生活中没有什么是那么容易,对吧?仔细看,因为细胞发生了一件特殊的事情。所有的文字被截断,即使有足够的水平空间。



这是因为视图细胞由界面构建器没有自动布局约束在默认情况下,但你需要他们的细胞适应列宽。


添加约束视图细胞

打开Main.storyboard。选择图像视图位于细胞内视图名称列,然后单击销按钮添加以下三个约束:

  • Leading: 3
  • Height: 17
  • Width: 17

保持图像选择并单击对齐按钮在工具栏自动布局。容器中添加一个垂直对齐约束。


选择文本框在这个单元格看来,叫做表视图单元格和是一个NSTextField类类型。




添加以下约束:

  • Leading: 7
  • Trailing: 3
  • 垂直容器对齐约束

重复这个过程中的文本字段修改日期和大小的细胞,这些文本字段添加以下约束:


  • Leading: 3
  • Trailing: 3
  • 直容器对齐约束

构建、运行,然后选择一个文件夹。



现在您可以调整列和看到文本不是截断哪里有足够的空间。太棒了!


表视图交互


在本节中,您将使用一些改善UI交互。

响应用户的选择

当用户选择一个或多个文件,应用程序应该更新信息在底栏显示文件夹和文件的总数有多少选择。

为了通知然后选择表视图的变化,你需要实现tableViewSelectionDidChange(_:)方法的委托。这种方法将由表视图调用当它检测到的改变选择。

将此代码添加到ViewController实现:

<span style="font-size:18px;">func updateStatus() {
 
  let text:String
  // 1
  let itemsSelected = tableView.selectedRowIndexes.count
 
  // 2
  if ( directoryItems == nil ) {
    text = ""
  }
  else if( itemsSelected == 0 ) {
    text =   "\(directoryItems!.count) items"
  }
  else
  {
    text = "\(itemsSelected) of \(directoryItems!.count) selected"
  }
  // 3
  statusLabel.stringValue = text
}</span>

这种方法更新状态标签文本基于用户的选择。

表视图的索引属性selectedRowIndexes包含选定的行。知道有多少项被选中,它只是获取数组。

基于项目的数量,这个构建信息文本字符串。

设置变更状态标签文本。

现在,你只需要调用该方法当用户更改表格视图选择。添加下面的代码在表视图委托扩展:

<span style="font-size:18px;">func tableViewSelectionDidChange(notification: NSNotification) {
  updateStatus()
}</span>

选择更改时调用此方法表视图,然后更新状态文本。

构建和运行。




试试自己;在表视图中选择一个或多个文件,看信息文本的变化来反映您的选择。


应对双击


在OS X中,双击通常意味着用户触发一个动作,你的程序需要执行它。

例如,当你处理文件通常预计,双击运行文件打开的默认应用程序和一个文件夹,你希望看到它的内容。

现在你要实现双击反应。

不通过双击通知表视图委托,相反,他们派作为一个行动表视图的目标。但在视图控制器接收这些通知,您需要设置表格视图的目标和双作用的属性。


注意:Target-action模式的大多数控件使用可可通知事件。

如果你不熟悉这个模式中,你可以了解它的Target-Action 部分苹果OS X的可可应用能力文档。


添加下面的代码在viewDidLoad ViewController的()方法:

<span style="font-size:18px;">tableView.target = self
tableView.doubleAction = "tableViewDoubleClick:"</span>

这告诉表视图,视图控制器将成为其行动的目标,然后设置双击后将被调用的方法。

添加tableViewDoubleClick(:)方法实现:

<span style="font-size:18px;">func tableViewDoubleClick(sender: AnyObject) {
 
  // 1
  guard tableView.selectedRow >= 0 , let item = directoryItems?[tableView.selectedRow] else {
    return
  }
 
  if item.isFolder {
    // 2 
    self.representedObject = item.url
  } else {
    // 3  
    NSWorkspace.sharedWorkspace().openURL(item.url)
  }
}</span>

上面的代码逐步爆发:

如果表视图选择是空的,它并没有并返回。还请注意,双击表格视图的一个空的区域将导致一个视图。selectedRow值等于1。

如果是文件夹,它设置representedObject属性项的URL。然后表格视图刷新显示该文件夹的内容。

如果项目是一个文件,它打开它在默认应用程序通过调用NSWorkspace方法openURL()

构建、运行和检查你的杰作。

双击任何文件,观察它在默认的应用程序打开。现在选择一个文件夹,看看表视图刷新并显示该文件夹的内容。

哇,等等,你只创建一个DIY版仪吗?肯定是这样!

整理资料

每个人都喜欢好人,下一节中,您将了解如何排序表视图基于用户的选择。

一个表是一个最好的特性之一——或者双击就通过一个特定的列进行排序。一键将它按升序排序,第二次点击将按照降序排列。

实现这一特定UI很容易因为NSTableView包大部分的开箱即用的功能。

类型描述符是什么您将使用来处理这一点,他们只是NSSortDescriptor类的实例,指定所需的属性和排序顺序。

建立描述符后这是发生了什么:单击列标题在表视图将通知您,通过委托,应该使用哪个属性,然后用户可以对数据进行排序。

一旦你设置的描述符,表视图提供了所有UI处理排序,点击标题、箭头和通知的类型描述符被选中。然而,这是你的责任顺序数据根据这一信息,并刷新表格视图反映了新秩序。

您将学习如何做现在。


添加以下代码里面viewDidLoad()来创建描述符:

<span style="font-size:18px;">// 1
let descriptorName = NSSortDescriptor(key: Directory.FileOrder.Name.rawValue, ascending: true)
let descriptorDate = NSSortDescriptor(key: Directory.FileOrder.Date.rawValue, ascending: true)
let descriptorSize = NSSortDescriptor(key: Directory.FileOrder.Size.rawValue, ascending: true)
 
// 2
tableView.tableColumns[0].sortDescriptorPrototype = descriptorName;
tableView.tableColumns[1].sortDescriptorPrototype = descriptorDate;
tableView.tableColumns[2].sortDescriptorPrototype = descriptorSize;</span>

这是什么这段代码:

创建一个描述符每列进行排序,配有一个关键。、名称、日期、大小表示的属性文件列表可以命令。

添加类描述符通过设置每一列其sortDescriptorPrototype财产。

当用户单击列标题,表格视图将调用数据源方法tableView(_:sortDescriptorsDidChange:oldDescriptors:),此时应用程序应该对数据排序的基础上提供的描述符。

将下面的代码添加到数据源扩展:

<span style="font-size:18px;">func tableView(tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
  // 1
  guard let sortDescriptor = tableView.sortDescriptors.first else {
    return
  }
  if let order = Directory.FileOrder(rawValue: sortDescriptor.key! ) {
    // 2
    sortOrder = order
    sortAscending = sortDescriptor.ascending
    reloadFileList()
  }
} reloadFileList()</span>

这段代码如下:

获取第一个描述符对应于用户单击列标题。

分配的排序方式和sortAscending属性视图控制器,然后调用reloadFileList()。

早些时候你设置它得到一个数组排序的文件和告诉表格视图重新加载数据。

构建和运行。


点击任何头来看到你的表视图数据。再次单击相同的标题之间交替升序或降序的顺序进行排列。

您已经构建了一个使用一个表格视图文件查看器。恭喜你!


从这里去哪里


你可以在这里下载完成的项目。

OS X NSTableView教程覆盖了不少,你现在应该感觉更有自信在你使用表视图来组织数据的能力。此外,您还覆盖:

表视图的基础建设,包括标题的独特品质,行、列和单元格

如何添加列显示更多数据

如何识别各种组件供以后参考

如何加载数据表中

如何约束和截断有关吗

如何应对各种用户交互

有很多你可以做表视图为你的应用创建优雅的UI。如果你想了解更多关于它,考虑以下资源:


苹果的Mac表视图编程指南Table View Programming Guide for Mac

WWDC 2011 - 120视频会议基础NSTableView基础到高级视图View Based NSTableView Basic to Advanced

TableViewPlayGround示例代码包含源创建不同类型的自定义表视图。

如果你有任何问题或评论本教程,请加入以下讨论的论坛!谢谢你加入我!



原文地址:http://www.raywenderlich.com/118835/os-x-nstableview-tutorial






评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值