将选择器存储为NSDictionary中的值

时间:2010-05-12 20:41:27

标签: cocoa cocoa-touch nsdictionary selector

有没有办法将选择器存储在NSDictionary中,而不将其存储为NSString

5 个答案:

答案 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 *加入SELNSValue的最佳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