关于iphone:代表的非保留阵列

Non-retaining array for delegates

在CocoaTouch项目中,我需要一个特定的类,它不仅有一个委托对象,而且有许多委托对象。

看起来我应该为这些代表建立一个非安全阵列;问题是,NSARRAY将保留所有这些代表,但不应保留这些代表(根据公约,对象不应保留其代表)。

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


不久前我发现了这段代码(不记得该把它归于谁)。

它是相当巧妙的,使用一个类别来允许创建一个可变数组,这个数组不需要保留/释放,只需要用一个带有适当回调的CFArray来支持它。

1
2
3
4
5
6
7
8
9
10
11
@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


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

johnmph建议使用[NSValue valueWithNonretainedObject:]

注意,当您这样做时,您的引用在nsvalue对象中的行为与__weak不同,而与__unsafe_unretained不同。更具体地说,当你试图取回你的引用(使用[MynsValue UnrestainedObjectValue])时,如果对象在此时间之前被释放,你的应用程序将与一个exc_bad_访问信号崩溃!

换句话说,弱引用在NSValue对象内不会自动设置为nil。我花了好几个小时才弄明白。我通过创建一个只有弱引用属性的简单类来解决这个问题。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 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


使用非保持对象方法检查nsvalue值的文档:

This method is useful for preventing an object from being retained when it’s added to a collection object (such as an instance of NSArray or NSDictionary).


我建议不要与该框架作斗争,不要像这样使用nsponterray和NSPointerFunctionsWeakMemoryNSPointerFunctionOption

1
2
3
4
5
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.

在场景中为我提供了很好的服务,在场景中,我必须设计一个委托数组,该数组自动为空的引用。


你不想这样做!CocoaTouch有几个发送事件的概念,您应该为每个案例使用适当的概念。

  • 目标操作:用于UI控件,如按钮按下。一个发送者,零个或多个接收器。
  • 代表:仅针对一个发送者和一个接收者。
  • 通知:对于一个发送者,以及零个或多个接收者。
  • kvo:更细粒度的通知。
  • 您应该做的是研究如何使用NSNotificationCenter类。这是发送具有多个接收器的通知的正确方法。


    这个来自Nimbus的更简单:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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);
    }


    我从three20项目中找到了一些关于这个主题的代码,我希望这有助于…

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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);
    }

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


    在数组或字典中存储怎么样

    1
    __weak typeof(pointer) weakPointer = pointer;

    我找到一个名为xmppframewrok的开源库

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

    https://github.com/robbiehanson/xmppframework/wiki/multicastdelegate