如何向NSMutableArray添加活动对象,并在发布时删除它们? [英] How to add alive object to NSMutableArray and remove them when they're released?

查看:255
本文介绍了如何向NSMutableArray添加活动对象,并在发布时删除它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有类Item和类List(它有一个NSMutableArray)。

I have class Item and class List (which has an NSMutableArray).

每一个类Item被实例化(并销毁)它发布一个通知由类List。当类List接收通知时,将类Item的实例添加到它的列表中。

Every time class Item is instantiated (and destroyed) it posts a notification, which is listened-to by class List. When class List receives the notification is adds the instance of class Item to its list.

我试图让类Item也发布一个通知, 'd。问题是类List的NSMutableArray保留类Item的实例。

I'm trying to have class Item also post a notification that its about to be dealloc'd. The problem is that class List's NSMutableArray retains the instance of class Item.

处理这种情况最合适的方法是什么?如果我在将它添加到List的数组时减少计数,那么当类List尝试调用removeObject时会抛出异常(因为它将尝试对该对象进行dealloc)。

What's the most appropriate means of handling this situation? If I decrement the count when adding it to List's array, then an exception will be thrown when class List attempts to call removeObject (since it'll try to dealloc the object.)

基本上,我想要一个监视器类List,其中包含所有live实例的列表。但是,我还需要能够释放/ dealloc的实例,并让他们报告他们正在dealloc'd所以List可以从它的NSMutableArray中删除它们。

Basically, I want a "monitor" class List that contains a list of all "live" instances of Item. But, I also need the ability to release/dealloc the instances and have them report they're being dealloc'd so List can remove them from its NSMutableArray.

感谢你的帮助。

推荐答案

如果我理解正确,你需要一个数组维护弱项引用, ?

If I understand correctly, you want an array that maintains weak references to its items, as opposed to strong references?

我不知道在Cocoa中使用任何内置方法。我知道这样做的唯一方法是使自己的数组,并有存储 __ weak id [] 。当对象释放时,它会自动将数组中的位置置零。如果您处于保留版本模式下,则可以使用 MAZeroingWeakRef 获得相同的行为。

I don't know of a way to do this with anything "built-in" in Cocoa. The only way I'd know of to do this is to make the array yourself, and have the storage be __weak id[]. That would automatically zero-out the place in the array when the object deallocates. If you're under the retain-release model, you could use something like MAZeroingWeakRef to get the same behavior.

这绝对是一个有趣的问题,我不知道一个更容易的答案。

This is definitely an interesting question, and I don't know of an easier answer. I'd love to be proven wrong!

哈,我爱错了!

有一个类名为 NSPointerArray ,看起来像它可以做你想要的。但是,它只能在Mac上使用,而且只有在使用垃圾收集时才会自动调零。

There's a class called NSPointerArray that looks like it can do what you're looking for. However, it's only available on the Mac, and it only auto-zeros when you're using garbage collection.

我会继续考虑这个问题。这是一个有趣的问题! :)

I'll keep thinking about this. This is an interesting problem! :)

所以我一直在思考这个问题,并提出了一个解决方案。它使用两个非常规的东西:

So I kept thinking about this, and came up with a solution. It uses two unconventional things:


  1. NSMutableArray / li>
  2. 使用关联对象确定对象释放

  1. A subclass of NSMutableArray (egads!)
  2. Using an associated object to determine object deallocation

对于第一个位,子类 NSMutableArray ,以便我可以注入一些自定义逻辑到 addObject:(和相关方法)。我不想通过swizzling这样做,因为 NSArray 和朋友是一个类集群,并且swizzling进入/离开集群充满了危险。所以,一个子类。这很好,但是我们会失去一些我们从pure NSArray 实例中获得的真棒特性,例如当他们变得大的时候他们做什么奇怪的事情

For the first bit, I had to to subclass NSMutableArray so that I could inject some custom logic into addObject: (and related methods). I didn't want to do this via swizzling, since NSArray and friends are a class cluster, and swizzling into/out of clusters is fraught with peril. So, a subclass. This is fine, but we're going to lose some of the awesome features we get from "pure" NSArray instances, like how they do weird things when they get big. Oh well, such is life.

对于第二个位,我需要一个任何任意对象的方式来通知它即将完成解除分配。我想到动态子类化对象的类,注入我自己的 dealloc / finalize 方法,调用超级,然后粉碎对象的 isa ,但是看起来有点太疯狂了。

As for the second bit, I needed a way for any arbitrary object to notify that it is about to or just finished deallocating. I thought of dynamically subclassing the object's class, injecting my own dealloc/finalize method, calling super, and then smashing the isa of the object, but that just seemed a little too crazy.

所以,我决定利用一个有趣的小东西称为关联对象。这些是为了ivars什么类别是类:它们允许您在运行时动态添加和删除伪实例变量。他们也有自动清理与对象释放的真棒副作用。所以我做的只是创建了一个抛弃对象,当 被释放时发布通知,然后将其附加到常规对象。这样,当正则对象被释放时,抛弃对象也会被释放,导致通知被发布,然后我在 NSMutableArray 子类中监听。通知包含指向正在被销毁的对象的(陈旧的)指针,但由于我只关心指针而不是对象,那就没关系了。

So, I decided to take advantage of a fun little thing called associated objects. These are to ivars what categories are to classes: they allow you to dynamically add and remove pseudo-instance variables at runtime. They also have the awesome side effect of getting automatically cleaned up with the object deallocates. So what I did is just created a little throw away object that posts a notification when it is deallocated, and then attached it to the regular object. That way when the regular object is deallocated, the throw away object will be as well, resulting in a notification being posted, which I then listen for in the NSMutableArray subclass. The notification contains a (stale) pointer to the object that is in the process of getting destroyed, but since I only care about the pointer and not the object, that's OK.

所有这一切的结果是你可以做:

The upshot of all of this is that you can do:

DDAutozeroingArray *array = [DDAutozeroingArray array];

NSObject *o = [[NSObject alloc] init];
[array addObject:o];
NSLog(@"%ld", [array count]); //logs "1"
[o release];
NSLog(@"%ld", [array count]); //logs "0"

源代码在github上,在iOS上为Mac OS X(无论GC模式): https://github.com/davedelong/Demos

The source is on github, and it should (theoretically) work just as well on iOS as Mac OS X (regardless of GC mode): https://github.com/davedelong/Demos

干杯!

...我只是想办法在没有自定义子类的情况下这样做,但我累了,并且明天会发布更新的答案。

... and I just thought of a way to do this without a custom subclass, but I'm tired and will post the updated answer tomorrow.

第二天早上...

the next morning...

我刚刚更新了Github上的项目,其中包含 NSMutableArray 类别,允许您创建一个真正的 NSMutableArray ,在对象被释放时自动将其对象置零。诀窍是创建一个 CFMutableArrayRef 和一个自定义 retain 回调,设置正确的观察,然后只是转换 CFMutableArrayRef NSMutableArray 并使用那个(啊,Toll-Free Bridging的魔力)。

I've just updated the project on Github with an NSMutableArray category that allows you to create a true NSMutableArray that auto-zeroes its objects as they're deallocated. The trick was to create a CFMutableArrayRef with a custom retain callback that sets up the proper observation, and then just cast that CFMutableArrayRef to an NSMutableArray and use that (ah, the magic of Toll-Free Bridging).

这意味着你现在可以:

NSMutableArray *array = [NSMutableArray autozeroingArray];

我添加了一个 typedef NSAutozeroingMutableArray ,只是为了明确说明这是一个 NSMutableArray ,它不会 retain 其对象,如普通的 NSMutableArray 。但是,由于它只是一个 typedef ,而不是一个子类,你可以互换使用它们。

I added a typedef to define these as NSAutozeroingMutableArray, just to make it explicitly clear that while this is an NSMutableArray, it doesn't retain its objects like a normal NSMutableArray. However, since it's just a typedef and not a subclass, you can use them interchangeably.

这篇关于如何向NSMutableArray添加活动对象,并在发布时删除它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆