Ben*_*ard 5 cocoa key-value-observing nsarraycontroller cocoa-bindings
在调用更新底层数组的方法时,如何更新绑定到NSArrayController的tableView需要做什么?一个例子可能会澄清这一点.
当我的应用程序启动时,它会创建一个SubwayTrain.当SubwayTrain初始化时,它会创建一个SubwayCar.SubwayCar有一个可变的阵列'乘客'.当地铁车辆初始化时,乘客阵列被创建,并且放入几个人物对象(假设有一个名为"票务收集者"的人和另一个名为"无家可归者"的人).这些人总是在SubwayCar上,所以我在初始化时创建它们并将它们添加到乘客阵列.
在应用程序的生命周期中,人们登上了汽车.在SubwayCar上调用'addPassenger',并将此人作为参数传入.
我有一个NSArrayController绑定到subwayTrain.subwayCar.passengers,并在启动时我的收票员和无家可归的人显示正常.但是当我使用[subwayCar addPassenger:]时,tableView不会更新.我已经确认乘客肯定被添加到阵列中,但是在gui中没有任何更新.
我可能做错了什么?我的直觉是它与KVO相关 - 当调用addPassenger时,阵列控制器不知道更新(即使addPassenger调用[passenger addObject:].我在这里可能会出错 - 如果有帮助我可以发布代码).
感谢愿意帮忙的人.
UPDATE
所以,事实证明我可以通过改变addPassenger方法来实现这一点
[seatedPlayers addObject:person];
Run Code Online (Sandbox Code Playgroud)
至
NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers];
[newSeatedPlayers addObject:sp];
[seatedPlayers release];
[self setSeatedPlayers:newSeatedPlayers];
Run Code Online (Sandbox Code Playgroud)
我想这是因为我正在使用[self setSeatedPlayers].这是正确的方法吗?复制数组,释放旧数组并更新副本(而不是仅添加到现有数组)似乎非常麻烦.
小智 7
我不知道它是否被认为是一个错误,但addObject :(和removeObject:atIndex :)不生成KVO通知,这就是数组控制器/表视图没有得到更新的原因.要符合KVO,请使用mutableArrayValueForKey:
例:
[[self mutableArrayValueForKey:@"seatedPlayers"] addObject:person];
Run Code Online (Sandbox Code Playgroud)
您还需要实现insertObject:inSeatedPlayersAtIndex:因为默认的KVO方法非常慢(它们创建一个全新的数组,将该对象添加到该数组,并将原始数组设置为新数组 - 非常低效)
- (void)insertObject:(id)object inSeatedPlayerAtIndex:(int)index
{
[seatedPlayers insertObject:object atIndex:index];
}
Run Code Online (Sandbox Code Playgroud)
请注意,当数组控制器添加对象时,也会调用此方法,因此它也可以作为注册撤消操作等的一个很好的钩子.
所以,事实证明我可以通过 addPassenger 方法进行更改来使其工作
Run Code Online (Sandbox Code Playgroud)[seatedPlayers addObject:person];到
Run Code Online (Sandbox Code Playgroud)NSMutableSet *newSeatedPlayers = [NSMutableSet setWithSet:seatedPlayers]; [newSeatedPlayers addObject:sp]; [seatedPlayers release]; [self setSeatedPlayers:newSeatedPlayers];我想这是因为我正在使用
[self setSeatedPlayers]. 这是正确的做法吗?
首先,它是setSeatedPlayers:, 和冒号。这在 Objective-C 中至关重要。
使用您自己的设置器是正确的方法,但您使用的方法不正确。它有效,但您仍然编写了超出需要的代码。
您应该做的是实现集合访问器,例如addSeatedPlayersObject:. 然后,向自己发送该消息。这使得添加人员成为一句简短的话:
[self addSeatedPlayersObject:person];
Run Code Online (Sandbox Code Playgroud)
只要您遵循符合 KVC 的访问器格式,您将免费获得 KVO 通知,就像您使用setSeatedPlayers:.
与此相比的优点setSeatedPlayers:是:
我也更喜欢这个解决方案mutableSetValueForKey:,不仅是为了简洁,而且因为很容易拼错该字符串文字中的键。(Uli Kusterer 有一个宏可以在发生这种情况时发出警告,当您确实需要与 KVC 或 KVO 本身对话时,这很有用。)