objective-c – ARC下归零弱引用的集合

objective-c – ARC下归零弱引用的集合,第1张

概述如何获得ARC下的归零弱引用数组?我不想让数组保留对象。我想要数组元素在被释放时删除自己,或者将这些条目设置为nil。 同样,我怎么能用字典呢?我不想让字典保留值。再次,我希望字典元素要么在值被释放时删除自己,要么将值设置为nil。 (我需要保留键,这是唯一的标识符,至少直到相应的值被释放)。 这两个问题涉及类似的理由: > NSArray of weak references to object 如何获得ARC下的归零弱引用数组?我不想让数组保留对象。我想要数组元素在被释放时删除自己,或者将这些条目设置为nil。

同样,我怎么能用字典呢?我不想让字典保留值。再次,我希望字典元素要么在值被释放时删除自己,要么将值设置为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下归零弱引用的集合所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1045929.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存