2010-12-05 25 views
2

我正在尝试创建一个半复杂的视图动画集(想想NSMatrix表单的动画版本,其中行随着其他行的添加或删除而滑动),并构建我制作的动画助手类。使用NSView实例作为NSDictionary键?

在那里,我必须跟踪不同的视图,它们的有序索引以及与它们的动画相关的一些其他值。

为此,我使用NSArray实例来跟踪视图的排序(索引),并且我想使用带有视图的NSDictionary作为键来跟踪值(值本身在嵌套字典中)。即我希望能够做到这事,例如(伪代码):

NSMutableDictionary* viewValuesDict = [NSDictionary dictionary]; 

// Loop thru an ordered NSArray 
for((NSView*) view in viewsArray) { 
    // Get some values we'll need later 
    NSDictionary* associatedValues = [view getSomeValues]; 

    // ...and put them into viewValuesDict... 
    [viewValuesDict setObject:associatedValues forKey:view]; 

    // and then things break because the NSView 'view' 
    // doesn't support copyWithZone.... darn 
} 

问题是,我当然不能用NSView实例作为字典键,因为键使用添加的copyWithZone,其中NSView未执行。

那么,什么是获得NSView实例的唯一密钥的好方法?我可以想象使用[obj description],因为你获得的内存地址是一个完美的UID,但是当然系统必须与任何类型的NSView子类一起工作,这可能会完全返回其他东西,所以这没有用。

或者我应该尝试一些其他的东西?有没有可能替代NSDictionary,钥匙只是不复制?因为在这种情况下,我真的不需要复制密钥。

回答

8

有时会出现一些情况,您希望使用视图(无论是NS还是UI)作为词典中的键。我遇到过这种情况。我宁愿使用objc_setAssociatedObject,但这需要雪豹。与NSValue拳击将工作,但如果你需要做很多很多的查找视图,连续拳击和拆箱的指针可能会变得乏味。

有两种选择来创建NSView => <object>字典。

  1. 使用NSMapTable
  2. 使用CFMutableDictionaryRef

NSMapTable是10.5推出的一类,这是非常类似于NSMutableDictionary,除了它具有额外的能力,使得它与垃圾收集更多的工作很好。在你的情况下,你可能会想要一个带有“弱”键和“强”值的映射表,但阅读所有有趣细节的文档。

CFMutableDictionaryRefNSDictionary的核心基金会等价物(它们是免费桥接的),但它有一些额外的创建选项。您使用CFDictionaryCreateMutable()创建一个,并且需要两个struct参数。一种是定义如何处理字典键的内存管理(和其他)行为的结构,另一种是定义值行为的struct。您可以创建一个CFMutableDictionaryRef,其中包含保留键(而不是复制它们)然后保留这些值的选项。完成此操作后,您可以将CFMutableDictionaryRef转换为NSMutableDictionary并按照您的预期使用它,只需保留这些密钥而不是复制。

0

创建您的字典,以便其中一个值是视图;然后重新排列代码,以便不必根据视图查找词典,而是从词典或索引开始(将词典放入数组中)或者自己创建的唯一ID(将词典放入字典;对于每个新视图,ID可以像连续数字一样简单,然后开始跟踪)。除非你正在做一些非常复杂和动态的事情,否则应该可以避免只需要查询NSView

+0

谢谢。是的,我也在想这个。我只是想到,只有使用任何ol对象作为关键的方法。看起来(至少对我来说)使用对象作为键将是一个简单的方法来“伪造”对象上的一些额外属性(我希望类别会以某种方式让你添加ivars ......叹息)。 – Flambino 2010-12-05 21:39:59

+0

不是。键具有真正特定的属性;这正是使字典有效的原因。如果你真的想为每个NSView添加一些额外的属性,为什么不是继承?这正是子类的用途! – andyvn22 2010-12-06 03:41:06

+0

因为代码必须在任何视图上运行,而不仅仅是特定的子类。此外,它只是在很短的时间内存储一些相关的值(足够长的时间来准备生成的NSViewAnimation,但就是这样),所以虽然我可以做一些对象组合并包装NSViews,但它看起来像是矫枉过正。无论如何,NSMapTable工作出色:-) – Flambino 2010-12-06 09:44:14

1

正如andyvn22所说,重组!但是,如果这不实际:

  • 如果您的目标是雪豹,并且关联可能会在视图的整个生命周期内持续存在,请使用objc_setAssociatedObject()
  • 否则,请使用[NSValue valueWithNonretainedObject:]而不是-description。 (像它说,它不保留对象,但你的阵列一样。)
+0

重组可以完成,但我希望有一个快捷方式:-)我的目标是雪豹,但我只需要很短的时间内的值,所以我认为,我会跳过`objc_setAssociatedObject()`。但`valueWithNonretainedObject:`可能是要走的路。我会试试看 - 谢谢! – Flambino 2010-12-05 21:44:55

2

使用NSMapTable,而不是NSDictionary(当然你必须确保,如果你仔细管理对象生存不使用垃圾收集)。 This article对如何使用它有很好的总结。

相关问题