2

给定以下代码:

    NSMutableArray *a = [NSMutableArray array];
    NSMutableArray *b = [NSMutableArray array];

    [a addObject:b];
    [b addObject:a];

当我将 a 和 b 设置为 NIL 时,有哪些选项可以使数组对象解除分配?

我尝试了一些事情(比如弱引用),但它似乎不起作用..(可能是因为我不太了解 - 对目标 c 的新手)。

很想得到一些帮助。

谢谢你

4

4 回答 4

0

我不确定您如何尝试向数组添加弱引用,但如果是这样的话:

NSMutableArray *myArray = [NSMutableArray new]
__weak id weakObject = blah;
[myArray addObject:weakObject]

那么,weakObject 被声明为弱这一事实没有任何区别。它只会使堆栈中对您的对象的本地引用变弱。在您的情况下,数组需要持有对对象的弱引用,而 NSMutableArray 始终持有对其成员的强引用。

有几种方法可以做到这一点。CFArray 允许您在创建它时指定它应如何保留其成员。或者您可以将引用“装箱”在 NSValue 中,尽管该引用由数组保留,但不保留其内容。

如果您的目标是 Mac 或 iOS 6.0+,最好的解决方案是使用弱 NSPointerArray(使用 创建[NSPointerArray weakObjectsPointerArray])。

这比在普通 NSMutableArray 中使用 CFArray 或 NSValue 更好,因为当引用的对象被释放时,数组元素将自动设置为 nil。

于 2013-07-17T21:28:27.730 回答
0

这里有解释:非保留数组代表

您可以使用

+ (NSValue *)valueWithNonretainedObject:(id)anObject

并将 NSValue 放入数组中。

或者这样做:

NSMutableArray* NICreateNonRetainingMutableArray(void) {
  return (NSMutableArray *)CFArrayCreateMutable(nil, 0, nil);
}

NSMutableDictionary* NICreateNonRetainingMutableDictionary(void) {
  return (NSMutableDictionary *)CFDictionaryCreateMutable(nil, 0, nil, nil);
}

NSMutableSet* NICreateNonRetainingMutableSet(void) {
  return (NSMutableSet *)CFSetCreateMutable(nil, 0, nil);
}
于 2013-07-17T18:50:51.710 回答
0

您可以使用以下方法使整个数组不保留其元素:CFArrayCreate()

如果您不再使用元素然后在以后遍历数组,这在 ARC 中可能会出现问题。

于 2013-07-17T19:02:06.360 回答
0

这种事情的一种解决方案是将您的对象包装在一个弱代理对象中。这是此类对象的示例实现:

https://github.com/jha/jalib-core/blob/master/JALibCore/Helpers/JAWeakProxy.h

https://github.com/jha/jalib-core/blob/master/JALibCore/Helpers/JAWeakProxy.m

然后你可以这样做:

NSMutableArray* a = [NSMutableArray array];
NSMutableArray* b = [NSMutableArray array];
[a addObject:[JAWeakProxy weakProxyWithTarget:b]];
[b addObject:[JAWeakProxy weakProxyWithTarget:a]];

现在两者都在数组ab被弱引用。使用弱代理对象的好处是您不需要“拆箱”其中的真实对象 - 您可以直接在弱代理对象上发送消息(调用方法),就好像它是那样target,它会通过一起留言。例如:

[a[0] addObject:@(0)];

注意a[0]实际上是如何返回持有b它的弱代理对象的target,但是我可以addObject直接发送到这个弱代理表示b(它是一个NSMutableArray),并且弱代理的实现将确保消息被转发到b

但是,您确实会丢失一些编译时类型检查,因此这种技术最好用于帮助某些类的内部实现,这些类将具有访问和枚举内容的类型良好的方法。

当我使用这些东西时,我通常会在数组枚举器中放入一些自动清理代码。也就是说,我将数组隐藏在实用程序类中并提供基于块的枚举方法,并且我还保留了一个toRemove数组。target迭代时,我跳过已自动归零的任何对象nil并将它们添加到toRemove数组中(弱代理对象即使它target消失了仍然存在),然后我遍历toRemove数组并删除代理对象。您还可以检查是否target存在nil并将其添加到toRemove任何访问器助手中的数组中。

于 2013-07-17T19:04:15.953 回答