在 NSOutlineView 中使用 Swift 结构

问题描述 投票:0回答:4

我正在尝试使用 Swift 结构作为其项目来填充

NSOutlineView
。这是可行的,除了
row(forItem:)
方法之外,它总是返回 -1。 我已确保我的结构符合
Equatable
并实现了
isEqual
函数。仍然
NSOutlineView
找不到任何项目的行。

如果我将结构转换为类(不是从 NSObject 派生),那么一切都有效。即使不遵守

Equatable
或实现任何
isEqual
功能。

我认为 Swift 中的类和结构体基本上是相同的,除了一个是引用类型,另一个是值类型。

我需要实现什么才能将 Swift 结构用作

NSOutlineView
中的项目?

swift cocoa
4个回答
3
投票

有人在苹果开发者论坛上发布了类似的问题

NSOutlineView 在识别项目时不使用 Equatable,它使用指向该项目的引用指针。在 Swift 中,结构总是按值传递(而不是按引用传递),因此大纲视图永远不会识别出您传递的项目是相同的。将你的结构切换到类可以解决这个问题,因为 Swift 对类使用引用传递。

不幸的是,无法将结构用作与 NSOutlineView 一起使用的项目,您将需要使用类。

阅读这个答案,了解有关 Swift 如何使用按引用传递与按值传递的更多详细信息。


3
投票

macOS 10.14 的发行说明指出,如果 Swift 值类型同时符合 Equatable 和 Hashable 协议,则 NSOutlineView 将成功使用该值类型。

但是,如果您针对较旧的 SDK 进行构建,则值类型确实无法与 NSOutlineView 一起使用。


0
投票

由于这是一个永无止境的问题,我将添加更多有关 NSOutlineView 数据源的结构和类之间的确定的信息。

如果您没有时间完成阅读,您可以使用结构或类中的值填充 NSOutlineView。你选择。

模型

您始终使用数据模型来存储和获取数据。最佳实践是将模型隐藏在模型控制器后面。从那时起,您的 OutlineView 将永远不会真正查看数据源。

数据源委托。

该控件使用委托者来填充字段。从那时起,您将扫描模型以获取值。您可以使用对类成员和结构值的引用来填充控件。控制装置没有对数据进行反馈。控件本身从不直接更改数据。 如果更改模型中的值,只要它是类或结构,控件将不会对此类更改做出反应。需要重新加载以反映更改。在重新加载过程中,控件会替换所有数据。它不会通过

didSet
方法观察数据或将值汇集到类属性中。

拖放

如果您在控件中实现拖放功能,您将面临值传输问题。大纲视图和表格视图中的拖放技术基于粘贴板概念。 即使您使用类作为数据源,您也会在拖动开始时复制类实例,并立即丢失对源的任何硬引用。您将为大纲视图条目实现一些 ID 属性来解决此问题。它将破坏基于类的数据源的纯度,并将基于类的数据隐式转换为基于结构的数据或一种混合数据。

来自控制器的数据更新

如果控件更新数据(这是可能的),那么它必须使用某种 NSTextFields 作为视图或单元格。子类文本字段无法更改数据,但可以存储模型记录的 ID(结构)或引用(类)。它会在文本更新时触发

@objc func
,然后如果您愿意,更新可能会影响模型控制器。正如我上面所说,模型控制器循环数据,自然会通过引用 ID 来匹配数据源。


-1
投票

您可以通过简单地查看所有行并返回相等行的索引来覆盖子类中的方法

row(forItem item: Any?)

© www.soinside.com 2019 - 2024. All rights reserved.