tags:

views:

193

answers:

2

This code is in a UITableViewController subclass viewDidLoad method. The UITableViewController subclass contains a test method.

It crashes without throwing an exception.

id dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys: @"some text", @"text", @selector(test), @"selector", nil]
+2  A: 

Use NSValue to wrap the selector:

// Set selector
SEL inSelector = @selector(something:);
NSValue *selectorAsValue = [NSValue valueWithBytes:&inSelector objCType:@encode(SEL)];
id dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"some text", @"text", selectorAsValue, @"selector", nil];

// Retrieve selector
SEL outSelector;
[(NSValue *)[dict objectForKey:@"selector"] getValue:&selector];
// outSelector can now be used as a selector, e.g. [self performSelector:outSelector]
pix0r
As a follow up, NSValue is the correct class for wrapping any non-object type in an object. NSPoint, NSRect and NSSize all have dedicated constructors and number types are wrapped by the subclass NSNumber but you can also wrap arbitrary structs and even wrap objects without retaining them.Note though... NSValue is for *typed* data. Arbitrary blocks of binary data should be wrapped by NSData.
Matt Gallagher
+4  A: 

pix0r's solution is good, but I usually prefer to use strings because they're more resilient to serialization and make the dictionary easier to read in debug output.

// Set selector
SEL inSelector = @selector(something:);
NSString *selectorAsString = NSStringFromSelector(inSelector);
id dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"some text", @"text", selectorAsString, @"selector", nil];

// Retrieve selector
SEL outSelector = NSSelectorFromString([dict objectForKey:@"selector"]);
Rob Napier
I agree with this. SEL maps more naturally to a string (since it's a name) than a value (which usually represents C scalars and structs).
Chuck