无法在服务应用程序

时间:2018-06-19 01:38:26

标签: objective-c cocoa nstableview nspanel

字面上疯了。

我有一个服务应用,可以打开一个非常简单的NSPanel,其中包含NSTableView,一个标签和三个NSButton控件。

就是这样。

表视图是基于视图的,并且在IB中定义了四个不同的NSTableCellView行。

表格代码很简单;我的NSWindowController子类既是数据源又是委托。在大多数情况下,一切都很完美:

  • 窗口打开
  • 预期的数据源方法(numberOfRowsInTableView:tableView:objectValueForTableColumn:row:)被称为
  • 该表将通过其视图和节分隔符填充 tableView:isGroupRow:tableView:viewForTableColumn:row:
  • 禁用空选择,因此委托会立即收到 tableView:shouldSelectRow:消息,并自动显示表格 选择第一行
  • 表格完全按照原样显示,第一行被选中

一切看起来都很完美,但我无法选择不同的行。我在表格中点击的任何内容都不会改变选择。

我试过了:

  • 继承NSTableCellView并验证其正在接收hitTest:来电
  • 尝试“黑客”表格单元格视图hitTest:,因此它始终返回nil
  • 在表格单元格视图内的控件视图中尝试了“拒绝第一响应者”,“已启用”,“可编辑”属性的各种组合
  • 尝试删除所有控件视图。所以表格单元格视图为空
  • 尝试实施tableView:selectionIndexesForProposedSelection:而不是tableView:shouldSelectRow:
  • NSPanel更改为常规NSWindow

似乎没有任何区别。我在表格中点击的任何内容都不会更改选择,我的表格视图委托也不会再接收tableView:shouldSelectRow:次呼叫。

请注意,窗口中的所有其他(NSButton)控件都可以正常工作。我可以点击其中任何一个。

更新#1

根据评论,我尝试将产品更改为普通的.app,但没有区别。

我的下一步是使用委托方法进行更多操作,并将问题缩小到这个范围:

  • 如果我实现tableView:shouldSelectRow:,该表会调用我的委托方法两次(因为我已关闭“空选择”),表必须首先确定哪一行选择为默认值,所以我得到两个调用,一个用于行0(否),第二个用于行1(是))。但是,如果我在表格中点击,我再也没有收到另一个tableView:shouldSelectRow:

  • 如果删除tableView:shouldSelectRow:的实现,表格选择会神奇地开始起作用。 (除了您可以选择组行,这是故事。)

  • 还尝试实施tableView:selectionIndexesForProposedSelection:而不是tableView:shouldSelectRow:;相同的行为

因此,如果我实现任何委托方法来确定哪些行是可选择的,那么我就无法选择任何行。 叹息

更新#2

我惩罚并重构了应用程序,因此现在有一个新的视图控制器对象专用于管理表视图(而不是重载窗口控制器)。所有数据模型和委托方法都被移动到新的视图控制器。

另外(认为IB中的表视图可能有些奇怪),我从NIB中删除了表视图并重新创建了它及其所有连接。

不幸的是,这些变化都没有任何区别。如果实现tableView:shouldSelectRow:,则该表不可用。删除该方法,它再次有效。

更新#3

它只是变得更奇怪:我认为我可以“破解”行选择问题,我实现了表视图委托方法tableViewSelectionIsChanging:tableViewSelectionDidChange:。没有人打电话。即使我删除tableView:shouldSelectRow:,允许表格选择有效,也不会收到tableViewSelectionIsChanging:tableViewSelectionDidChange:

然而,如果我为NSTableViewSelectionIsChangingNotificationNSTableViewSelectionDidChangeNotification添加观察员,则会收到这些观察员。

另请注意,作为表视图的委托和数据源的NSViewController子类明确符合<NSTableViewDelegate><NSTableViewDataSource>,因此不应该有任何理由为什么表视图应该对于实施什么委托方法感到困惑。

1 个答案:

答案 0 :(得分:1)

赞!现在这很尴尬。

所以问题出在窗口控制器的参考上。

这就是正在发生的事情:正在创建,加载窗口控制器,并显示了窗口。在最初的演示和显示期间,所有操作都有效(tableView:shouldSelectRow:等),因为存在窗口和视图控制器。但是在将来的事件循环中,ARC销毁了窗口和视图控制器,仅在屏幕上保留了表视图,而对其委托和数据源对象的弱引用现在为零。

解决方案是修复窗口控制器管理,以便在关闭窗口之前一直对窗口控制器有强大的参考。

有时候,最简单的事情会让您绊倒...