セレクターをNSDictionary
として保存せずに、NSString
に保存する方法はありますか?
SEL
は単なるポインタであり、NSValue
に格納できます。
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithPointer:@selector(foo)], @"foo",
nil];
セレクターを元に戻すには、次を使用できます。
SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
Georgのソリューションの代替手段は、セレクターをNSDictionaryに格納する前にNSStringに変換することです。
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
NSStringFromSelector(@selector(foo)), @"foo",
nil];
SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);
この手法は、より多くのメモリを使用しますが、JSONKitなどのライブラリを介してNSDictionary全体を文字列としてシリアル化する機能を提供します。
NSDictionary
は、実際にはすべてのキーと値を保持および解放する単なるCFDictionary
です。 CFDictionary
を直接作成する場合は、値を保持および解放しないように設定できます。 CFDictionaryRef
をNSDictionary *
にタイプキャストすることもその逆も可能です。
UILocalNotification
を使用する場合、唯一の方法はNSSelectorFromString([dict objectForKey:@"foo"])
を使用することです。 valueWithPointer
で、UILocalNotification
オブジェクトのuserInfoプロパティを設定するとアプリがクラッシュします。注意してください。
Georgの回答 は機能するはずですが、NSValue
は、Objective-Cタイプのエンコーディング文字列を使用した任意の値のエンコーディングもサポートしています。これには、SEL
—を":"
("^v"
によって生成された-valueWithPointer:
とは対照的に、void *
に変換されます) 。
ソース: Objective-Cランタイムプログラミングガイド-タイプエンコーディング
Georgのソリューションを利用して、SEL
をNSValue
にNSDictionary
に配置するためのAPI準拠の最良の方法は次のとおりです。
// store
NSDictionary *dict = @{
@"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)]
};
// retrieve
SEL aSel;
[dict[@"foo"] getValue:&aSel];
SEL
をそれ自体の獣として扱う理由は、ドキュメントがそれを「不透明(OPAQUE)型」と記述していることです。つまり、その内部動作(typedef
dが何であっても)は立ち入り禁止ですアプリプログラマーへ。 Appleは、将来いつでもそれを混同する可能性があります。
また、void *
sを使用して、システムに必要な処理を強制することは、私たちのほとんどがそれ以上のことを知らなかった90年代のCで役立ちました。 あなたは今それよりも優れています。
上記のアプローチは、プログラムの実行中にSEL
の取得が行われる場合にのみ使用する必要があります。そのNSDictionary
をディスクに保存しないでください。 SEL
sを(アプリの起動全体で)長期間保存する必要がある場合は、 David Hのアプローチ に従い、NSString
に変換する必要があります。