Dav*_*vid 4 cocoa objective-c nsmutablearray
我有类Item和类List(有一个NSMutableArray).
每当类Item被实例化(并销毁)时,它都会发布一个通知,该通知由类List监听.当类List收到通知时,将类Item的实例添加到其列表中.
我正在尝试让课程项目也发布一个通知,它即将被释放.问题是类List的NSMutableArray保留了类Item的实例.
处理这种情况最合适的方法是什么?如果我在将它添加到List的数组时减少计数,那么当类List尝试调用removeObject时会抛出异常(因为它会尝试释放该对象.)
基本上,我想要一个"监视器"类列表,其中包含Item的所有"实时"实例的列表.但是,我还需要能够释放/释放实例并让它们报告它们被释放,因此List可以将它们从NSMutableArray中删除.
谢谢你的帮助.
Dav*_*ong 11
如果我理解正确,你想要一个维护对其项目的弱引用的数组,而不是强引用?
我不知道用Cocoa中的"内置"做任何事情的方法.我知道这样做的唯一方法就是自己制作阵列,并拥有存储空间__weak id[].当对象解除分配时,这会自动将数组中的位置清零.如果你在保留释放模型下,你可以使用类似的东西MAZeroingWeakRef来获得相同的行为.
这绝对是一个有趣的问题,我不知道一个更简单的答案.我很想被证明是错的!
哈,我喜欢错!
有一个类叫做NSPointerArray看起来像它可以做你想要的.但是,它仅在Mac上可用,并且当您使用垃圾收集时它只会自动为零.
我会一直想着这个.这是一个有趣的问题!:)
所以我一直在考虑这个问题,并想出了一个解决方案.它使用两种非传统的东西:
NSMutableArray(egads!)的子类对于第一位,我不得不进行子类化,NSMutableArray以便我可以将一些自定义逻辑注入addObject:(和相关方法).我不想通过调配这样做,因为NSArray和朋友是一个类集群,并且进入/离开集群充满了危险.所以,一个子类.这很好,但是我们将失去一些从"纯粹" NSArray实例中获得的一些很棒的功能,比如当它们变大时它们会做出奇怪的事情.哦,这就是生活.
至于第二位,我需要一种方法让任意对象通知它即将完成或者刚刚完成解除分配.我想过动态子类化对象的类,注入我自己的dealloc/ finalize方法,调用super,然后粉碎isa对象,但这似乎有点太疯狂了.
所以,我决定利用一个叫做相关对象的有趣小东西.这些是ivars类到哪些类:它们允许您在运行时动态添加和删除伪实例变量.它们还具有令人敬畏的副作用,即通过释放对象来自动清理它们.所以我做了什么,只是创造了一个小扔掉反对说,帖子时通知其被释放,然后将其连接到正规的对象.这样,当常规对象被释放时,扔掉的对象也将被释放,从而导致发布通知,然后我在NSMutableArray子类中监听.该通知包含一个(陈旧的)指针,该指针指向正在被销毁的对象,但由于我只关心指针而不是对象,所以没关系.
所有这一切的结果是你可以这样做:
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"
Run Code Online (Sandbox Code Playgroud)
源代码在github上,理论上它应该在iOS上与Mac OS X一样好(无论GC模式如何):https://github.com/davedelong/Demos
干杯!
...我只想到一种没有自定义子类的方法,但我很累,明天会发布更新的答案.
第二天早上......
我刚刚在Github上更新了一个NSMutableArray类别,该类别允许您创建一个真正NSMutableArray的对象,因为它们被取消分配时会自动将其对象归零.诀窍是创建一个CFMutableArrayRef自定义retain回调,设置正确的观察,然后将其CFMutableArrayRef转换为NSMutableArray并使用它(啊,免费桥接的魔力).
这意味着您现在可以:
NSMutableArray *array = [NSMutableArray autozeroingArray];
Run Code Online (Sandbox Code Playgroud)
我添加了一个typedef来定义这些NSAutozeroingMutableArray,只是为了明确地说明,虽然这是一个NSMutableArray,它retain的对象不像普通的那样NSMutableArray.但是,由于它只是一个typedef而不是子类,因此可以互换使用它们.
小智 5
我没有对此进行过测试,欢迎提出意见.
你可以使用一个NSPointerArray列表(在retain属性中):
self.array = [NSPointerArray pointerArrayWithWeakObjects];
Run Code Online (Sandbox Code Playgroud)
当一个Item对象被创建,它会发布这类由您听了通知List类.收到通知后,List将对象添加到指针数组:
[array addPointer:pointerToTheObject];
Run Code Online (Sandbox Code Playgroud)
在此设置中,指针数组不会对其元素保持强引用 - 特别是,它不会保留它们.这适用于垃圾收集和非垃圾收集的构建.
在垃圾收集的构建中,如果元素被垃圾收集,则垃圾收集器会自动分配NULL存储对象的数组中的位置.
在非垃圾收集的构建中,您需要手动删除元素或分配NULL到存储它的数组中的位置.您可以通过覆盖-[Item dealloc]并发布正在取消分配对象的通知来执行此操作.您的List班级在收到通知后会采取行动.
请注意,由于对象不属于指针数组,因此如果要使它们保持活动状态,则必须对它们保持强引用(或保留它们).
| 归档时间: |
|
| 查看次数: |
1108 次 |
| 最近记录: |