代表的非保留数组

时间:2011-01-14 14:37:47

标签: iphone cocoa-touch delegates nsarray retain

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

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

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

10 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:26)

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

Johnmph建议使用[NSValue valueWithNonretainedObject:]

请注意,执行此操作时,您的引用会像__weak一样而不是,而在NSValue对象中则更像__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

答案 2 :(得分:17)

检查NSValue valueWithNonretainedObject方法的文档:

  

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

答案 3 :(得分: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.

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

答案 4 :(得分:12)

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

  1. 目标操作:用于UI控件,例如按下按钮。一个发件人,零个或多个接收者。
  2. 代表:仅限一个发件人和一个收件人。
  3. 通知:一个发件人,零个或多个个收件人。
  4. KVO:通知更精细。
  5. 您应该做的是研究如何使用NSNotificationCenter课程。这是发送具有多个接收器的通知的正确方法。

答案 5 :(得分:3)

来自NIMBUS的这个会更简单:

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);
}

答案 6 :(得分:2)

我从Three20项目中找到了一些关于这个主题的代码,我希望这会有所帮助......

NSMutableArray* TTCreateNonRetainingArray() {
  CFArrayCallBacks callbacks = kCFTypeArrayCallBacks;
  callbacks.retain = TTRetainNoOp;
  callbacks.release = TTReleaseNoOp;
  return (NSMutableArray*)CFArrayCreateMutable(nil, 0, &callbacks);
}


NSMutableDictionary* TTCreateNonRetainingDictionary() {
  CFDictionaryKeyCallBacks keyCallbacks = kCFTypeDictionaryKeyCallBacks;
  CFDictionaryValueCallBacks callbacks = kCFTypeDictionaryValueCallBacks;
  callbacks.retain = TTRetainNoOp;
  callbacks.release = TTReleaseNoOp;
  return (NSMutableDictionary*)CFDictionaryCreateMutable(nil, 0, &keyCallbacks, &callbacks);
}

答案 7 :(得分:1)

关键字:NSHashTable,在文档中搜索。

答案 8 :(得分:0)

我找到了一个名为XMPPFramewrok

的开源库

项目中有一个多播委托解决方案

https://github.com/robbiehanson/XMPPFramework/wiki/MulticastDelegate

答案 9 :(得分:0)

如何存储在数组或字典中

__weak typeof(pointer) weakPointer = pointer;