将select器作为值存储在NSDictionary中
有没有办法将select器存储在NSDictionary
,而不将其存储为NSString
?
SEL
只是一个指针,你可以存储在一个NSValue
:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: [NSValue valueWithPointer:@selector(foo)], @"foo", nil];
要返回select器,可以使用:
SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
Georg的解决scheme的另一种select是将select器转换为NSString,然后再存储NSDictionary:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: NSStringFromSelector(@selector(foo)), @"foo", nil]; SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);
这种技术虽然使用了更多的内存,但却可以让您通过类似JSONKit的库将整个NSDictionary作为string进行序列化。
NSDictionary
实际上只是一个保留和释放所有键和值的CFDictionary
。 如果直接创buildCFDictionary
,可以将其设置为不保留和释放值。 你可以将一个CFDictionaryRef
types转换为一个NSDictionary *
,反之亦然。
在使用UILocalNotification
的情况下,唯一的方法是使用NSSelectorFromString([dict objectForKey:@"foo"])
。 在设置UILocalNotification
对象的userInfo属性时, valueWithPointer
导致应用程序崩溃。 小心。
当Georg的答案应该可以工作的时候, NSValue
还支持使用Objective-Ctypes的编码string来编码任何值,这个编码string有一个特殊的表示SEL
– 用":"
(而不是由-valueWithPointer:
生成的"^v"
,这转换成void *
) 。
来源: Objective-C运行时编程指南 – types编码
根据Georg的解决scheme,将SEL
插入NSValue
成为NSDictionary
的最佳API方法是:
// store NSDictionary *dict = @{ @"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)] }; // retrieve SEL aSel; [dict[@"foo"] getValue:&aSel];
把SEL
当作自己的野兽的理由是,文档将其描述为“不透明的types” – 这意味着它的内部工作(即使是types定义)对应用程序员来说是不受限制的。 苹果可能会在未来的任何时候混合起来。
此外,使用void *
s强制系统做你想做的事情,在90年代C中是有用的,当时我们大多数人都不了解任何更好的东西。 你现在比这更好。
只有在程序运行持续时间内检索SEL
情况下,才能使用上述方法 – 不应将该NSDictionary
存储到磁盘。 如果您确实需要长期存储SEL
(跨应用程序启动),则应遵循David H的方法并将其转换为NSString
。