有没有办法将选择器存储在NSDictionary
中,而不将其存储为NSString
?
答案 0 :(得分:104)
SEL
只是一个指针,您可以将其存储在NSValue
:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSValue valueWithPointer:@selector(foo)], @"foo",
nil];
要重新选择选择器,您可以使用:
SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
答案 1 :(得分:10)
Georg的解决方案的替代方案是将选择器转换为NSString,然后将其存储为NSDictionary:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
NSStringFromSelector(@selector(foo)), @"foo",
nil];
SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);
这种技术虽然使用了更多的内存,但是你可以通过像JSONKit这样的库将整个NSDictionary序列化为一个字符串。
答案 2 :(得分:6)
NSDictionary
实际上只是一个保留并释放所有键和值的CFDictionary
。如果直接创建CFDictionary
,则可以将其设置为不保留和释放值。您可以将CFDictionaryRef
类型转换为NSDictionary *
,反之亦然。
答案 3 :(得分:3)
如果使用UILocalNotification
,唯一的方法是使用NSSelectorFromString([dict objectForKey:@"foo"])
。使用valueWithPointer
时,应用程序在设置UILocalNotification
对象的userInfo属性时崩溃。小心。
答案 4 :(得分:2)
虽然Georg's answer应该有效,NSValue
也支持使用Objective-C类型编码字符串编码任何值,该字符串具有表示SEL
的特殊方式 - {{1 }} (与":"
生成的"^v"
相对,后者转换为-valueWithPointer:
)。
来源:Objective-C Runtime Programming Guide - Type Encodings
使用Georg的解决方案,将void *
加入SEL
到NSValue
的最佳API兼容方式是:
NSDictionary
将// store
NSDictionary *dict = @{
@"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)]
};
// retrieve
SEL aSel;
[dict[@"foo"] getValue:&aSel];
作为自己的野兽处理的理由是,文档将其描述为“不透明的类型” - 这意味着它的内部工作(甚至是它的SEL
d)都是关闭的 - 应用程序员的限制; Apple可能会在将来的任何时候混淆它。
此外,使用typedef
强制系统执行您想要的操作在90年代的C中很有用,因为我们大多数人都不知道更好。 你现在比现在好。
只有在程序运行期间检索void *
时才应使用上述方法 - 您不应将SEL
存储到磁盘。如果您确实需要存储NSDictionary
长期(跨应用启动),您应该关注David H's approach并将其转换为SEL
。