在源列表中显示固定和可编辑的项目
Posted
技术标签:
【中文标题】在源列表中显示固定和可编辑的项目【英文标题】:Displaying fixed and editable items in a Source List 【发布时间】:2009-11-28 11:31:11 【问题描述】:背景
我正在为我的应用程序创建一个源列表,我希望它的结构类似于 iTunes,包含两种类型的项目:
“固定”项目——这些项目不会改变,也不能移动——在顶部 下方的可编辑项目,可由用户更改 - 移动、重命名等(在 iTunes 示例中,例如播放列表和智能播放列表)在我的 iTunes 类比中:
(来源:perspx.com)
到目前为止,我构建数据的方式如下:
我想要编辑的项目是“组”项目,形式为Group
Core Data 实体。
源列表中的每个项目都表示为SourceListItem
常规 Objective-C 对象,以便我可以将每个项目与标题、图标、子项目等相关联
固定项当前由SourceListItem
实例表示,存储在我的控制器对象的数组中。
问题
我不确定如何将这两种类型的项目合并到源列表中,以便固定项目在顶部并且始终存在并且不会更改,而可编辑项目在底部并且可以移动并编辑。
这些是我迄今为止提出的想法:
将固定项添加到核心数据模型。这意味着我可以创建一个实体来表示源列表项,并将我的固定和可编辑项放置在这些实例中。然后这些可以绑定到带有数组/树控制器的大纲视图表列。但是,这意味着我必须创建一个新实体来表示源列表项,然后将Group
s 与此同步。我还必须有某种方法只创建一次所有固定项目,如果任何持久存储文件发生问题,则不会显示固定项目。
将固定项与组项合并。虽然两者都存储在单独的数组中,但当大纲视图请求数据时,这可以在我的窗口的控制器中完成(如果采用NSOutlineViewDataSource
协议,而不是绑定)。然而,这意味着我必须为数组控制器中的每个组创建新的SourceListItem
s(将每个组与图标和其他属性相关联),存储这些,然后观察组数组控制器的更改以删除、添加或修改对组进行更改时的 SourceListItem
实例。
有人对我如何实现这个有更好的想法吗?
我希望我的应用程序与 OS X v10.5 兼容,因此我更喜欢不依赖于安装 Snow Leopard 的任何解决方案。
【问题讨论】:
【参考方案1】:我正在开发一个具有完全相同行为的应用程序,我是这样做的:
我的核心数据模型中有 5 个主要实体:
AbstractItem
- 一个抽象实体,具有所有项目共有的属性,如 name
、weight
和 editable
。还有两个关系:parent
(与AbstractItem
的一对一关系)和children
(与AbstractItem
的一对多关系,与parent
相反)。
Group
- AbstractItem
的具体子实体。
Folder
- AbstractItem
的具体子实体。向基本 Item
实体添加多对多关系。
SmartFolder
- Folder
的具体子实体。添加二进制属性predicateData
。覆盖Folder
的“items”关系访问器,以返回使用predicateData
属性定义的谓词执行提取请求的结果。
DefaultFolder
- SmartFolder
的具体子实体。添加字符串属性identifier
。
对于“库”部分的项目,我插入 DefaultFolder
对象并给它们一个唯一标识符,以便我可以轻松检索它们并区分它们。我还给他们一个NSPredicate
,它对应于他们应该显示的Items
。例如,“音乐”DefaultFolder
将有一个谓词来检索所有音乐项目,“播客”DefaultFolder
将有一个谓词来检索所有播客项目,等等。
根级项目(“Library”、“Shared”、“Store”、“Genius”等)都是 Group
具有 nil
父项的项目。无法编辑的组和文件夹的editable
属性设置为NO
。
至于在大纲视图中实际获取这些内容,您必须自己实现NSOutlineViewDataSource
和NSOutlineViewDelegate
协议。这里有太多的行为复杂性,无法通过NSTreeController
将其抽出。然而,在我的应用程序中,我在不到 200 行代码中获得了所有行为(甚至是拖放)(所以它并没有那么糟糕)。
【讨论】:
很好的答案,谢谢。然而,我对纯核心数据路由的主要关注是关于创建始终存在的“固定”项目(在你的情况下是库项目)——你是否只是在加载时测试它们是否已经在模型中如果没有,则创建它们? @Perspx - 因为我给了它们唯一标识符(@"Music"
、@"Podcasts"
等),所以我可以获取所有 DefaultFolders
,检查我有哪些,然后创建我没有的不。 (简短回答:是的)
AbstractItem
的weight
属性的用途是什么?还是仅针对您正在建模的数据?
@jbrennan - 由于 CoreData 将所有内容都存储为集合,因此它不会保持顺序。我使用weight
属性来记住用户放置物品的顺序。权重越低,列表中的位置越高。列表中的第一件事的权重为零。每次用户在同一级别添加新的AbstractItem
或用户拖放时,都会动态重新计算此权重。
我还应该说我称它为“重量”,因为当我使用 Drupal 时就是这样称呼它的。也许“订单”可能是一个更好的名字。【参考方案2】:
不要仅仅为了支持视图而在数据集中注入废话。这不仅违背了 MVC 设计模式,而且给最重要的部分:用户数据的管理增加了不必要的复杂性(即“更多潜在的错误”)。
也就是说,在这种特殊情况下使用绑定是造成如此多摩擦的原因。为什么不完全避开绑定?我认为,使用 NSOutlineViewDataSource 协议,您走在正确的轨道上,但您做得还不够远。相反,完全依赖这个(仍然完全有效并且在某些方面更优越)协议。
您实际上是在用易于设置(和易于更改通知)换取对树结构的完全控制。
【讨论】:
是的,我认为你是对的;我只是认为绑定是一种潜在的实现方式。我确实更喜欢NSOutlineViewDataSource
协议的想法,但是像这样将数据拼凑在一起似乎有点笨拙,正如我所说,这也意味着我需要注意核心数据Group
实例的变化以反映这些变化SourceListItem
s 的数组
这没有什么不妥之处。在 Mac OS X 10.3 之前,这是唯一的方法(在 Cocoa 中)。也没有必要将所有内容集中在一起作为一个结构。您的组是根项目。每个组的孩子都是一个结果数组。没有问题,没有混乱,没有内疚。 :-)以上是关于在源列表中显示固定和可编辑的项目的主要内容,如果未能解决你的问题,请参考以下文章
EditView不可编辑状态和可编辑状态动态切换 及 EditView的其它特效
如何在HTML / Javascript中创建可编辑的组合框?