web-dev-qa-db-ja.com

セレクターを値としてNSDictionaryに格納します

セレクターをNSDictionaryとして保存せずに、NSStringに保存する方法はありますか?

54
synic

SELは単なるポインタであり、NSValueに格納できます。

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                       [NSValue valueWithPointer:@selector(foo)], @"foo",
                       nil];

セレクターを元に戻すには、次を使用できます。

SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
104
Georg Fritzsche

Georgのソリューションの代替手段は、セレクターをNSDictionaryに格納する前にNSStringに変換することです。

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                      NSStringFromSelector(@selector(foo)), @"foo",
                      nil];

SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);

この手法は、より多くのメモリを使用しますが、JSONKitなどのライブラリを介してNSDictionary全体を文字列としてシリアル化する機能を提供します。

10
David H

NSDictionaryは、実際にはすべてのキーと値を保持および解放する単なるCFDictionaryです。 CFDictionaryを直接作成する場合は、値を保持および解放しないように設定できます。 CFDictionaryRefNSDictionary *にタイプキャストすることもその逆も可能です。

6
drawnonward

UILocalNotificationを使用する場合、唯一の方法はNSSelectorFromString([dict objectForKey:@"foo"])を使用することです。 valueWithPointerで、UILocalNotificationオブジェクトのuserInfoプロパティを設定するとアプリがクラッシュします。注意してください。

3
kostas

Georgの回答 は機能するはずですが、NSValueは、Objective-Cタイプのエンコーディング文字列を使用した任意の値のエンコーディングもサポートしています。これには、SEL—を":""^v"によって生成された-valueWithPointer:とは対照的に、void *に変換されます)
ソース: Objective-Cランタイムプログラミングガイド-タイプエンコーディング

Georgのソリューションを利用して、SELNSValueNSDictionaryに配置するためのAPI準拠の最良の方法は次のとおりです。

// store
NSDictionary *dict = @{
    @"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)]
};

// retrieve
SEL aSel;
[dict[@"foo"] getValue:&aSel];



SELをそれ自体の獣として扱う理由は、ドキュメントがそれを「不透明(OPAQUE)型」と記述していることです。つまり、その内部動作(typedefdが何であっても)は立ち入り禁止ですアプリプログラマーへ。 Appleは、将来いつでもそれを混同する可能性があります。

また、void *sを使用して、システムに必要な処理を強制することは、私たちのほとんどがそれ以上のことを知らなかった90年代のCで役立ちました。 あなたは今それよりも優れています。

上記のアプローチは、プログラムの実行中にSELの取得が行われる場合にのみ使用する必要があります。そのNSDictionaryをディスクに保存しないでください。 SELsを(アプリの起動全体で)長期間保存する必要がある場合は、 David Hのアプローチ に従い、NSStringに変換する必要があります。

2