Skip to content
Selectors and Method Pointers
step 1/5

Reading — step 1 of 5

Learn

~2 min readCollections, Control Flow, Selectors

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 method
  • performSelector: — 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 closureslet 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…