在Cocoa Touch项目中,我需要一个特定的类,不仅要有一个委托对象,还要有很多委托对象。
看起来我应该为这些代表创建一个NSArray; 问题是NSArray会保留所有这些代理,它不应该保留(按惯例对象不应该保留它们的代理)。
我应该编写自己的数组类来防止保留还是有更简单的方法? 谢谢!
答案 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)
我建议不要与框架作斗争,并将NSPointerArray与NSPointerFunctionsWeakMemory
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有几个发送事件的概念,你应该为每个案例使用正确的概念。
您应该做的是研究如何使用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;