Cocoa Touchプロジェクトでは、単一のデリゲートオブジェクトだけでなく、それらの多くを持つ特定のクラスが必要です。
これらのデリゲート用にNSArrayを作成する必要があるようです。問題は、NSArrayがこれらすべてのデリゲートを保持することですが、保持するべきではありません(慣例により、オブジェクトはデリゲートを保持するべきではありません)。
保持を防ぐために独自の配列クラスを作成する必要がありますか、それとももっと単純なメソッドがありますか?ありがとうございました!
私はしばらく前にこのコードを見つけました(誰に起因するのか思い出せません)。
カテゴリを使用して、適切なコールバックを使用して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つの重要な制限を提示します。
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
NSValue valueWithNonretainedObjectメソッドのドキュメントを確認してください:
このメソッドは、オブジェクトがコレクションオブジェクト(NSArrayやNSDictionaryのインスタンスなど)に追加されたときにオブジェクトが保持されないようにするのに役立ちます。
フレームワークと戦わずに 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の参照であるデリゲート配列を設計する必要があるシナリオで私はうまく機能しました。
あなたはこれをしたくない! Cocoa Touchには、イベントを送信するためのいくつかの概念があります。それぞれの場合に適切な概念を使用する必要があります。
あなたがすべきことは、NSNotificationCenter
クラスの使い方を調べることです。これは、複数の受信者がいる通知を送信する適切な方法です。
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);
}
このトピックに関する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);
}
キーワード:NSHashTable
、ドキュメントを検索します。
XMPPFramewrok という名前のオープンソースライブラリを見つけました
プロジェクトにはマルチキャストデリゲートソリューションがあります
https://github.com/robbiehanson/XMPPFramework/wiki/MulticastDelegate
配列や辞書に保存するのはどうですか
__weak typeof(pointer) weakPointer = pointer;