Swift 将CollectionDifference应用于NSTableView
对于本例,假设我从annSwift 将CollectionDifference应用于NSTableView,swift,macos,cocoa,Swift,Macos,Cocoa,对于本例,假设我从annInt数组生成一个CollectionDifference,然后像这样调用inferringMoves a=[18,18,19,11] 设b=[11,19] 设diff=b.difference(from:a).inferringMoves() 对于差异的变化{ 开关变换{ 案例let.insert(偏移量,u,关联): 如果let from=关联{ 打印(“移动”、起始、偏移) }否则{ 打印(“插入”,偏移) } 案例let.remove(偏移量,u,关联): //如
Int
数组生成一个CollectionDifference
,然后像这样调用inferringMoves
a=[18,18,19,11]
设b=[11,19]
设diff=b.difference(from:a).inferringMoves()
对于差异的变化{
开关变换{
案例let.insert(偏移量,u,关联):
如果let from=关联{
打印(“移动”、起始、偏移)
}否则{
打印(“插入”,偏移)
}
案例let.remove(偏移量,u,关联):
//如果是移动,则已记录在中。插入
如果关联==nil{
打印(“删除”,偏移)
}
}
}
现在我需要获取changes数组并将其提供给nstableview
update方法
insertRows
dows
moveRow
move
条目的偏移量。上面的代码段生成:
REMOVE 1
REMOVE 0
MOVE 2 1
remove(offset: 2, element: 19, associatedWith: 1)
remove(offset: 1, element: 18, associatedWith: -)
remove(offset: 0, element: 18, associatedWith: -)
insert(offset: 1, element: 19, associatedWith: 2)
[18, 18, 19, 11]
remove(offset: 1, element: 18, associatedWith: -) => [18, 19, 11]
remove(offset: 0, element: 18, associatedWith: -) => [19, 11]
insert(offset: 2, element: 19, associatedWith: 0) => [11, 19]
a move: insert at offset, remove at associatedWith
现在很明显,我不能为0
和1
调用RemoveOWS
,然后调用moveRow(2,1)
,但这就是差异的建议
我怎样才能干净地使用它
问题似乎是
NSTableView在应用插入/删除操作时会立即更新其内部计数,因此移动将不起作用。简短回答:
inferringMoves()
不会做您认为它会做的事情。仔细查看结果,特别是与
相关的值,并开发一种算法,该算法实际生成所需的删除、插入和移动–inferringMoves()
实际上不会生成任何移动
长答案:
你的问题引起了我的兴趣,因为我以前从来没有看过CollectionDifference
,所以我会去看看。第一步是在互联网上搜索,这会找到苹果的文档(和往常一样糟糕,它是为那些已经知道语义的人编写的,为什么他们不能再提供像样的文档了——大部分像样的东西都在他们的“档案”中,但我有分歧……)和一些描述该功能的网站,包括示例代码。该示例代码中有相当一部分与您的代码不同,但也不必为此感到难过,因为它也不起作用
为什么这么长时间的闲逛?发现没有工作代码让人怀疑你是否患有“锁定热”,你的大脑是否混乱。所有的代码真的不起作用吗?它适用于某些数据集,但不适用于一般情况,苹果称beastinferringMoves
有点不正确,它推断出序列中的移除和插入操作对,这些操作一起具有移动项目的效果,但实际上并没有推断出单个移动操作
或者我可能(比平时)更糊涂的大脑是这么说的。继续读下去,决定我是否有闭锁症
让我们看看您的数据,看看差异产生了什么,以及每个步骤如何更改输入:
Input: [18, 18, 19, 11]
Sequence of changes from `difference` and the changing sequence:
remove(offset: 2, element: 19, associatedWith: -) => [18, 18, 11]
remove(offset: 1, element: 18, associatedWith: -) => [18, 11]
remove(offset: 0, element: 18, associatedWith: -) => [11]
insert(offset: 1, element: 19, associatedWith: -) => [11, 19] CORRECT
在这个序列中重要的是,任何步骤的偏移量
都考虑了前面的所有步骤,也就是说,它是中间结果的偏移量
现在inferringMoves
设置与关联的字段,以指示构成移动的移除/插入
对,将其应用于数据的差异
:
REMOVE 1
REMOVE 0
MOVE 2 1
remove(offset: 2, element: 19, associatedWith: 1)
remove(offset: 1, element: 18, associatedWith: -)
remove(offset: 0, element: 18, associatedWith: -)
insert(offset: 1, element: 19, associatedWith: 2)
[18, 18, 19, 11]
remove(offset: 1, element: 18, associatedWith: -) => [18, 19, 11]
remove(offset: 0, element: 18, associatedWith: -) => [19, 11]
insert(offset: 2, element: 19, associatedWith: 0) => [11, 19]
a move: insert at offset, remove at associatedWith
因此,第一个和最后一个动作被推断为移动对
您决定,并且不是唯一一个做出该决定的人,插入操作是应该执行移动的时间,让我们看看会发生什么:
[18, 18, 19, 11]
remove(offset: 2, element: 19, associatedWith: 1) => [18, 18, 19, 11]
Noop as part of a move pair
remove(offset: 1, element: 18, associatedWith: -) => [18, 19, 11]
Item 1 was 18 so this seems valid...
remove(offset: 0, element: 18, associatedWith: -) => [19, 11]
Item 0 is not 18 so this looks like things are going wrong
insert(offset: 1, element: 19, associatedWith: 2) => Oops
Second action of a move pair, Error item 1 is not 19 and there is no item 2
正如你在医院发现的那样,这不管用。互联网上的其他人认为这是一个移动的移动,他们有更好的表现吗
[18, 18, 19, 11]
remove(offset: 2, element: 19, associatedWith: 1) => [18, 19, 18, 11]
First of pair, do the move
remove(offset: 1, element: 18, associatedWith: -) => [18, 18, 11]
Warning bell the item removed is 19 not 18 as the action expects
remove(offset: 0, element: 18, associatedWith: -) => [18, 11]
Yah, item 0 is 18, this action is "correct" in isolation
insert(offset: 1, element: 19, associatedWith: 2) => [18, 11]
Second of pair, so NOOP
这也不起作用,所以不要为你的代码不起作用而感到难过,因为我还没有在互联网上找到任何起作用的代码(这并不是说没有任何代码),出错的情况很常见,部分原因可能是许多简单的例子都是偶然发生的
解决这个问题的关键是要弄清楚(苹果没有明确说明)与
值关联的是一个索引,该索引将(用于将来的插入)或(用于过去的删除)在关联操作发生/发生时存在/存在的序列中受影响的索引
例如,数据的第一个操作是删除(偏移量:2,元素:19,关联:1)
,这并不意味着您可以将项目移动到当前序列中的索引1,而是移动到序列中的索引1,因为执行关联的插入(偏移量:1,元素:19,关联:2)
。在对的移除和插入之间有两个中间移除操作,因此顺序将发生变化
要获得(而不是唯一的)工作解决方案,您可以使用以下略图算法对inferringMoves()
的结果进行后期处理:
删除任何与
值关联的移除操作,并在所有后续操作中调整偏移量
值,以允许要移除的元素仍在序列中;及
将与
关联的值调整为未通过已删除的成对删除操作删除的元素的当前偏移量
这将产生一系列零或多个移除和插入操作,这些操作没有与
值关联的,以及一个或多个插入操作与表示移动的
值关联的
将上述算法草图的实现应用于数据会产生:
REMOVE 1
REMOVE 0
MOVE 2 1
remove(offset: 2, element: 19, associatedWith: 1)
remove(offset: 1, element: 18, associatedWith: -)
remove(offset: 0, element: 18, associatedWith: -)
insert(offset: 1, element: 19, associatedWith: 2)
[18, 18, 19, 11]
remove(offset: 1, element: 18, associatedWith: -) => [18, 19, 11]
remove(offset: 0, element: 18, associatedWith: -) => [19, 11]
insert(offset: 2, element: 19, associatedWith: 0) => [11, 19]
a move: insert at offset, remove at associatedWith
实现这个或另一个算法,就像不做代码编写服务一样,是留给您的。希望上面的解释有意义!如果你被你的工具卡住了