Reading — step 1 of 5
Learn
In Objective-C, methods are selectors — symbolic representations of method names. They let you store, pass, and dynamically dispatch method calls.
Selector basics
SEL action = @selector(uppercaseString);
SEL is just a name. You can apply it to any object:
NSString *s = @"hello";
if ([s respondsToSelector:@selector(uppercaseString)]) {
NSString *upper = [s performSelector:@selector(uppercaseString)];
printf("%s\n", [upper UTF8String]);
}
@selector(name:)— get a selector for a method (note the colon for methods with args)respondsToSelector:— check if object has this methodperformSelector:— call by selector
Selectors with arguments
[s performSelector:@selector(stringByAppendingString:) withObject:@" world"]
%% "hello world"
performSelector:withObject:withObject: for two args. Beyond two: use NSInvocation (more verbose).
Storing selectors
Dispatch tables become possible:
NSDictionary *handlers = @{
@"uppercase": [NSValue valueWithPointer:@selector(uppercaseString)],
@"lowercase": [NSValue valueWithPointer:@selector(lowercaseString)],
@"reverse": [NSValue valueWithPointer:@selector(stringByReversingString)]
};
Target-action pattern
Classic Cocoa:
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
%% On click, [self buttonClicked:button] is called.
This decoupling is fundamental to Cocoa's MVC.
Blocks (modern alternative)
Objective-C 2.0 (with C extensions) added blocks — lambda expressions. Most modern Cocoa code uses blocks instead of selectors:
int (^add)(int, int) = ^int(int a, int b) {
return a + b;
};
int result = add(3, 4); %% 7
The ^ is the block syntax. int (^add)(int, int) is a block-pointer type: "block taking two ints, returning int".
Blocks capture variables:
int multiplier = 5;
int (^times)(int) = ^int(int n) { return n * multiplier; };
times(3); %% 15
Blocks for collection iteration:
NSArray *nums = @[@1, @2, @3];
[nums enumerateObjectsUsingBlock:^(NSNumber *n, NSUInteger idx, BOOL *stop) {
printf("%lu: %d\n", idx, [n intValue]);
}];
Sorting with a block:
NSArray *sorted = [nums sortedArrayUsingComparator:^NSComparisonResult(NSNumber *a, NSNumber *b) {
return [b compare:a]; %% descending
}];
Selectors vs blocks
- Selectors — older, used in target-action, NSTimer, KVO
- Blocks — newer, much more common in modern code, can capture variables
Swift inherited blocks as closures — let f: (Int) -> Int = { x in x * 2 }. They're the same machinery underneath.
Why this matters
Objective-C's dynamism (selectors, message forwarding, dynamic typing) is what makes:
- Auto-generated UIs (Interface Builder)
- KVO (Key-Value Observing) for reactive code
- Dependency injection without DI frameworks
- Mocking for tests
Understanding selectors is essential for reading legacy Cocoa code and writing extensions to NSObject behavior.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…