代表的非保留数组

发布于 2024-10-12 11:08:00 字数 177 浏览 6 评论 0原文

在 Cocoa Touch 项目中,我需要一个特定的类来不仅拥有单个委托对象,而且拥有多个委托对象。

看起来我应该为这些委托创建一个 NSArray; 问题是 NSArray 会保留所有这些委托,但它不应该保留(按照惯例,对象不应保留其委托)。

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

In a Cocoa Touch project, I need a specific class to have not only a single delegate object, but many of them.

It looks like I should create an NSArray for these delegates;
the problem is that NSArray would have all these delegates retained, which it shouldn't (by convention objects should not retain their delegates).

Should I write my own array class to prevent retaining or are there simpler methods?
Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

捂风挽笑 2024-10-19 11:08:00

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

这是非常巧妙的,使用 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

I found this bit of code awhile ago (can't remember who to attribute it to).

It's quite ingenius, using a Category to allow the creation of a mutable array that does no retain/release by backing it with a CFArray with proper callbacks.

@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

EDIT Found the original article: http://ofcodeandmen.poltras.com

污味仙女 2024-10-19 11:08:00

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

Johnmph 建议使用 [NSValue valueWithNonretainedObject:]

请注意,当您执行此操作时,您的引用在 NSValue 对象内部的行为类似于 __weak,而是类似于 __unsafe_unretained。更具体地说,当您尝试取回引用时(使用 [myNSValue nonretainedObjectValue]),如果该对象在此之前已被释放,您的应用程序将崩溃并出现 EXC_BAD_ACCESS 信号!

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

更美妙的是,通过使用 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

I am presenting an important limitation of one of the earlier answers, along with an explanation and an improvement.

Johnmph suggested using [NSValue valueWithNonretainedObject:].

Note that when you do this, your reference acts not like __weak, but rather like __unsafe_unretained while inside the NSValue object. More specifically, when you try to get your reference back (using [myNSValue nonretainedObjectValue]), your application will crash with an EXC_BAD_ACCESS signal if the object has been deallocated before that time!

In other words, the weak reference is not automatically set to nil while inside the NSValue object. This took me a bunch of hours to figure out. I have worked around this by creating a simple class with only a weak ref property.

More beautifully, by using NSProxy, we can treat the wrapper object entirely as if it is the contained object itself!

// 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
雪化雨蝶 2024-10-19 11:08:00

检查 NSValue valueWithNonretainedObject 方法的文档:

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

Check documentation of NSValue valueWithNonretainedObject method :

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).

め可乐爱微笑 2024-10-19 11:08:00

我建议不要对抗框架并使用 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 的引用。

I'd suggest to not-fight-the-framework and use NSPointerArray with the NSPointerFunctionsWeakMemory NSPointerFunctionOption like this:

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.

Served me well in scenarios, where I had to design a delegates array, which auto-NULL's references.

七秒鱼° 2024-10-19 11:08:00

你不想这样做! Cocoa Touch 有几个发送事件的概念,您应该针对每种情况使用正确的概念。

  1. 目标操作:用于 UI 控件,例如按下按钮。一个发送者,零个或多个接收者。
  2. 委托:仅适用于一个发送者和一个接收者。
  3. 通知:适用于一个发送者和零个或多个接收者。
  4. KVO:比通知更细粒度。

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

You do not want to do this! Cocoa Touch have several concepts for sending events, you should use the proper concept for each case.

  1. Target-action: For UI controls, such as button presses. One sender, zero or more receivers.
  2. Delegates: For one sender and one receiver only.
  3. Notification: For one sender, and zero or more receivers.
  4. KVO: More fine grained that notifications.

What you should do is to look into how to use NSNotificationCenter class. This is the proper way to send a notification that have more than one receiver.

冷情 2024-10-19 11:08:00

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

This one from NIMBUS would be more simple:

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);
}
葬シ愛 2024-10-19 11:08:00

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

Keyword: NSHashTable, search in documentations.

书间行客 2024-10-19 11:08:00

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

I found some pieces of code from Three20 project about this topic, i hope this helps...

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);
}
GRAY°灰色天空 2024-10-19 11:08:00

我找到了一个名为 XMPPFramewrok 的开源库,

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

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

I found an open source library named XMPPFramewrok

There is a multicast delegate solution in the project

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

冰魂雪魄 2024-10-19 11:08:00

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

__weak typeof(pointer) weakPointer = pointer;

What about storing in the array or dictionary

__weak typeof(pointer) weakPointer = pointer;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文