使用 NSView 实例作为 NSDictionary 键?

发布于 2024-10-06 07:41:33 字数 1102 浏览 5 评论 0原文

我正在尝试创建一组半复杂的视图动画(想想 NSMatrix 表单的动画版本,其中行随着其他行的添加或删除而滑动),并构建我的动画正在制作一个小助手类。

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

为此,我使用 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 的方法,其中键不被复制?因为在这种情况下,我真的不需要复制密钥。

I'm trying to create a semi-complex set of view animations (think an animated version of an NSMatrix form, where rows slide around as other rows are added or removed), and to build the animation I'm making a little helper class.

There I have to keep track of the different views, their ordered indices, and few some other values associated with their animations.

To that end, I'm using an NSArray instance to keep track of the ordering (indices) of the views, and I'd like to use an NSDictionary with the views as keys to keep track of the values (the values themselves are in nested dictionaries). I.e. I'd like to be able to do something this, for instance (pseudo code):

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
}

Problem is, I of course can't use NSView instances as dictionary keys, because the keys are added using copyWithZone, which NSView does not implement.

So, what's a good way to get a unique key for an NSView instance? I could conceivably use [obj description] since the memory address you get back is a perfect UID, but of course the system has to work with any kind of NSView subclass that might return something else entirely, so that's no good.

Or should I maybe try something else entirely? Is there maybe some alternative to NSDictionary, where keys just aren't copied? Because in this case I really have no need for the keys to ever be copied.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

软甜啾 2024-10-13 07:41:33

有时,您希望使用视图(无论是 NS 还是 UI)作为字典中的键。我就遇到过这样一种情况。我更愿意使用 objc_setAssociatedObject,但这需要 Snow Leopard。使用 NSValue 进行装箱是可行的,但是如果您需要在给定视图中进行大量查找,则指针的连续装箱和拆箱可能会变得乏味。

创建 NSView => 有两个选项: 字典。

  1. 使用 NSMapTable
  2. 使用 CFMutableDictionaryRef

NSMapTable 是 10.5 中引入的一个类,它与 NSMutableDictionary 非常相似,除了它具有使其工作的额外功能垃圾收集效果更好。在您的情况下,您可能需要一个具有“弱”键和“强”值的映射表,但请阅读文档以了解所有有趣的详细信息。

CFMutableDictionaryRef 是相当于 NSDictionary 的 Core Foundation(它们是免费桥接的),但它有一些额外的创建选项。您可以使用 CFDictionaryCreateMutable() 创建一个,并且需要两个 struct 参数。一个是定义如何处理字典键的内存管理(和其他)行为的结构体,另一个是用于定义值的行为的struct。您可以创建一个 CFMutableDictionaryRef,其中包含保留键(而不是复制它们)然后保留值的选项。完成此操作后,您可以将 CFMutableDictionaryRef 转换为 NSMutableDictionary 并按您的预期使用它,只是键将被保留而不是复制。

Sometimes there are occasions where you want to use a view (whether NS or UI) as the key in a dictionary. I've come across one such situation. I would've preferred to use objc_setAssociatedObject, but that requires Snow Leopard. Boxing with NSValue will work, but if you need to be doing lots and lots of look ups given a view, the continual boxing and unboxing of pointers may become tedious.

There are two options to creating an NSView => <object> dictionary.

  1. Use NSMapTable
  2. Use CFMutableDictionaryRef

NSMapTable is a class introduced in 10.5 that is very similar to an NSMutableDictionary, except that it has extra abilities that make it work more nicely with garbage collection. In your case, you'll probably want a map table with "weak" keys and "strong" values, but read the documentation for all the fun details.

CFMutableDictionaryRef is the Core Foundation equivalent of an NSDictionary (they are toll-free bridged), but it has some extra creation options. You create one using CFDictionaryCreateMutable(), and that wants two struct parameters. One is a structure that defines the memory management (and other) behavior of how to deal with the keys of the dictionary, and the other is a struct for defining the behavior of the values. You can create a CFMutableDictionaryRef with the options of retaining the keys (instead of copying them) and then retaining the values. Once you've done this, you can cast the CFMutableDictionaryRef to an NSMutableDictionary and use it as you'd expect, just that the keys will be retained instead of copied.

中二柚 2024-10-13 07:41:33

使用 NSMapTable 而不是 NSDictionary (当然,如果您不使用垃圾回收,则必须确保仔细管理对象的生命周期)。 这篇文章很好地总结了如何使用它。

Use NSMapTable instead of NSDictionary (of course you'll have to be sure to manage your object lifetimes carefully if you're not using garbage collection). This article has a good summary of how to use it.

苏大泽ㄣ 2024-10-13 07:41:33

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

  • 如果您的目标是 Sn​​ow Leopard,并且关联可能在视图的生命周期内持续存在,请使用 objc_setAssociatedObject() 。
  • 否则,请优先使用 [NSValue valueWithNonretainedObject:] 而不是 -description。 (就像它说的,它不保留对象,但你的数组保留。)

As andyvn22 said, reorganize! But if that isn’t practical:

  • If you’re targeting Snow Leopard, and the associations are likely to persist for the lifetime of the views, use objc_setAssociatedObject().
  • Otherwise, use [NSValue valueWithNonretainedObject:] in preference to -description. (Like it says, it doesn’t retain the object, but your array does.)
手心的温暖 2024-10-13 07:41:33

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

Create your dictionaries so that one of their values is the view; then rearrange the code so that you need not look up dictionary based on view, but rather begin either with the dictionaries, or the index (putting the dictionaries into an array), or a unique ID of your own creation (putting the dictionaries into a dictionary; the ID could be as simple as a consecutive number for each new view you begin to keep track of). Unless you're doing something very complicated and dynamic, it should be possible to avoid needing to look up information given only an NSView.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文