代表的非保留数组

wh1*_*t1k 43 iphone cocoa-touch delegates retain nsarray

在Cocoa Touch项目中,我需要一个特定的类,不仅要有一个委托对象,还要有很多委托对象.

看起来我应该为这些代表创建一个NSArray; 问题是NSArray会保留所有这些代理,它不应该保留(按惯例对象不应该保留它们的代理).

我应该编写自己的数组类来防止保留还是有更简单的方法?谢谢!

Mar*_*ell 48

我在前一段时间找到了这段代码(不记得是谁归于此).

它非常巧妙,使用Category来允许创建一个可变数组,该数组不会通过CFArray使用适当的回调来保留/释放.

@implementation NSMutableArray (WeakReferences)
    + (id)mutableArrayUsingWeakReferences {
    return [self mutableArrayUsingWeakReferencesWithCapacity:0];
    }

    + (id)mutableArrayUsingWeakReferencesWithCapacity:(NSUInteger)capacity {
    CFArrayCallBacks callbacks = {0, NULL, NULL, CFCopyDescription, CFEqual};
    // We create a weak reference array
    return (id)(CFArrayCreateMutable(0, capacity, &callbacks));
    }
@end
Run Code Online (Sandbox Code Playgroud)

编辑找到原始文章:http://ofcodeandmen.poltras.com

  • 就像使用临时NSValue对象存储弱引用的建议一样,我相信如果目标对象被释放,此解决方案将不会存储设置为nil的真正弱引用.不过这只是我的怀疑 - 如果我错了,请纠正我.最安全的方法可能仍然是定义你自己的helper对象提供一个weak属性,并将该helper对象存储在集合(数组,字典,集合)中,如NSArray使用注释中所建议的那样. (3认同)

Tim*_*imo 26

我提出了一个早期答案的重要限制,以及解释和改进.

Johnmph建议使用[NSValue valueWithNonretainedObject:].

请注意,执行此操作时,您的引用不会像NSValue对象中的那样__weak,而是更像__unsafe_unretained.更具体地说,当您尝试获取引用时(使用[myNSValue nonretainedObjectValue]),如果在此之前对象已被释放,则应用程序将使用EXC_BAD_ACCESS信号崩溃!

换句话说,弱NSValue对象在对象内部时不会自动设置为nil .这让我花了很多时间才弄明白.我通过创建一个只有弱ref属性的简单类来解决这个问题.

更美妙的是,通过使用NSProxy,我们可以完全将包装器对象视为包含的对象本身!

// WeakRef.h
@interface WeakRef : NSProxy

@property (weak) id ref;
- (id)initWithObject:(id)object;

@end


// WeakRef.m
@implementation WeakRef

- (id)initWithObject:(id)object
{
    self.ref = object;
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    invocation.target = self.ref;
    [invocation invoke];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [self.ref methodSignatureForSelector:sel];
}

@end
Run Code Online (Sandbox Code Playgroud)


Joh*_*mph 17

检查NSValue valueWithNonretainedObject方法的文档:

此方法可用于防止在将对象添加到集合对象(例如NSArray或NSDictionary的实例)时保留该对象.

  • 请注意,当您执行此操作时,您的引用不像__weak,而是在NSValue对象内部__unsafe_unretained.更具体地说,当您尝试获取引用时(使用[myNSValue nonretainedObjectValue]),如果在此之前对象已被释放,则应用程序将使用EXC_BAD_ACCESS信号崩溃.换句话说,在NSValue对象内部,弱引用不会自动设置为nil.这让我花了很多时间才弄明白.我通过创建一个只有弱ref属性的简单类来解决这个问题.添加到阵列,瞧! (25认同)
  • @Timo您的评论需要更多的可见性.发布它作为答案 (2认同)

lev*_*han 13

我建议不要拼-的框架,并使用NSPointerArrayNSPointerFunctionsWeakMemory NSPointerFunctionOption这样的:

NSPointerArray *weakReferencingArray = [NSPointerArray pointerArrayWithOptions:NSPointerFunctionsWeakMemory];

// NSPointerFunctionsWeakMemory - Uses weak read and write barriers 
// appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory 
// object references will turn to NULL on last release.
Run Code Online (Sandbox Code Playgroud)

在场景中我很好,我必须设计一个委托数组,自动NULL的引用.


Pey*_*loW 12

你不想这样做!Cocoa Touch有几个发送事件的概念,你应该为每个案例使用正确的概念.

  1. 目标操作:用于UI控件,例如按钮按下.一个发送者,零个或多个接收者.
  2. 代表:仅限一位发件人和一位收件人.
  3. 通知:对于一个发送者,以及零个或多个接收者.
  4. KVO:通知更精细.

你应该做的是研究如何使用NSNotificationCenter类.这是发送具有多个接收器的通知的正确方法.

  • 但是,*有*情况,其中非保留对象的集合是有用的. (10认同)