同样,我怎么能用字典呢?我不想让字典保留值。再次,我希望字典元素要么在值被释放时删除自己,要么将值设置为nil。 (我需要保留键,这是唯一的标识符,至少直到相应的值被释放)。
这两个问题涉及类似的理由:
> NSArray of weak references to objects under ARC@H_301_14@> Having a list of unretained id objects?
但两者都不是要求归零引用。
根据文档,NSPointerarray和NSHashMap都不支持ARC下的弱引用。 NSValue的nonretainedobjectValue也不会工作,因为它是非归零。
我看到的唯一的解决方案是创建我自己的NSValue类包装类有一个(weak)属性,如this answer mentions,near the end.有没有更好的方式,我没有看到?
我正在开发OS X 10.7和iOS 6.0。
解决方法 归零弱引用需要OS X 10.7或iOS 5。您只能在代码,ivars或块中定义弱变量。 AFAIK没有办法动态(在运行时)创建一个弱变量,因为ARC在编译时生效。当您运行代码时,它已经为您添加了保留和发布。
说过,你可以滥用块来实现这样的效果。
有一个只返回引用的块。
__weak ID weakref = strongref;[weakrefArray addobject:[^{ return weakref; } copy]];
请注意,您需要复制块以将其复制到堆。
现在你可以随时随地走阵列,在块中释放的对象将返回nil。然后,您可以删除这些。
当弱引用为零时,不能自动执行代码。如果这是你想要的,那么你可以利用相关对象的功能。那些被释放与它们相关联的对象的同时。所以你可以有自己的哨兵标记,通知弱集合关于物体灭亡。
你将有一个关联对象来观察dealloc(如果关联是唯一的引用),关联的对象将有一个指向集合观察的指针。然后在sentry dealloc中调用weak集合,通知它被监视的对象已经走了。
这是我的关于相关对象的写作:http://www.cocoanetics.com/2012/06/associated-objects/
这里是我的实现:
---- DTWeakCollection.h@interface DTWeakCollection : NSObject- (voID)checkInObject:(ID)object;- (NSSet *)allObjects;@end---- DTWeakCollection.m#import "DTWeakCollection.h"#import "DTWeakCollectionSentry.h"#import <objc/runtime.h>static char DTWeakCollectionSentryKey;@implementation DTWeakCollection{ NSMutableSet *_entrIEs;}- (ID)init{ self = [super init]; if (self) { _entrIEs = [NSMutableSet set]; } return self;}- (voID)checkInObject:(ID)object{ NSUInteger hash = (NSUInteger)object; // make weak reference NSNumber *value = [NSNumber numberWithUnsignedInteger:hash]; [_entrIEs addobject:value]; // make sentry DTWeakCollectionSentry *sentry = [[DTWeakCollectionSentry alloc] initWithWeakCollection:self forObjectWithHash:hash]; objc_setAssociatedobject(object,&DTWeakCollectionSentryKey,sentry,OBJC_ASSOCIATION_RETAIN);}- (voID)checkOutObjectWithHash:(NSUInteger)hash{ NSNumber *value = [NSNumber numberWithUnsignedInteger:hash]; [_entrIEs removeObject:value];}- (NSSet *)allObjects{ NSMutableSet *tmpSet = [NSMutableSet set]; for (NSNumber *oneHash in _entrIEs) { // hash is actually a pointer to the object ID object = (__brIDge ID)(voID *)[oneHash unsignedIntegerValue]; [tmpSet addobject:object]; } return [tmpSet copy];}@end---- DTWeakCollectionSentry.h#import <Foundation/Foundation.h>@class DTWeakCollection;@interface DTWeakCollectionSentry : NSObject- (ID)initWithWeakCollection:(DTWeakCollection *)weakCollection forObjectWithHash:(NSUInteger)hash;@end--- DTWeakCollectionSentry.m#import "DTWeakCollectionSentry.h"#import "DTWeakCollection.h"@interface DTWeakCollection (private)- (voID)checkOutObjectWithHash:(NSUInteger)hash;@end@implementation DTWeakCollectionSentry{ __weak DTWeakCollection *_weakCollection; NSUInteger _hash;}- (ID)initWithWeakCollection:(DTWeakCollection *)weakCollection forObjectWithHash:(NSUInteger)hash{ self = [super init]; if (self) { _weakCollection = weakCollection; _hash = hash; } return self;}- (voID)dealloc{ [_weakCollection checkOutObjectWithHash:_hash];}@end
这将像这样使用:
Nsstring *string = @"bla";@autoreleasepool {_weakCollection = [[DTWeakCollection alloc] init]; [_weakCollection checkInObject:string];__object = [NSNumber numberWithInteger:1123333];[_weakCollection checkInObject:__object];}
如果在autorelease pool块中输出allObjects,那么你有两个对象。外面你只有字符串。
我发现在dealloc的条目对象引用已经是nil,所以你不能使用__weak。相反,我使用对象的内存地址作为哈希。虽然这些仍然在_entrIEs中,您可以将它们视为实际对象,allObjects返回一个自动释放的强引用数组。
注意:这不是线程安全的。处理dealloc在非主队列/线程,你需要小心同步访问和改变内部_entrIEs集。
注意2:这当前只适用于检查单个弱集合的对象,因为第二次检入将覆盖相关的哨兵。如果你需要这个与多个弱集合,那么sentry应该有一个这些集合的数组。
注3:我将哨兵对集合的引用更改为弱,以避免保留循环。
注4:这里是一个typedef和帮助函数,它处理你的块语法:
typedef ID (^WeakReference)(voID);WeakReference MakeWeakReference (ID object) { __weak ID weakref = object; return [^{ return weakref; } copy];}ID WeakReferenceNonretainedobjectValue (WeakReference ref) { if (ref == nil) return nil; else return ref ();}总结
以上是内存溢出为你收集整理的objective-c – ARC下归零弱引用的集合全部内容,希望文章能够帮你解决objective-c – ARC下归零弱引用的集合所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)