Mobile Development 14 min read

Objective‑C Method Swizzling: Hook Order Analysis, Implementation Schemes, and Best Practices

This article examines Objective‑C method swizzling, compares two common implementation schemes, analyzes 18 inheritance‑hook scenarios for child‑first and parent‑first hook orders, and provides practical recommendations to ensure correct execution order and avoid crashes.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Objective‑C Method Swizzling: Hook Order Analysis, Implementation Schemes, and Best Practices

Objective‑C Hook, also known as Method Swizzling, is a dynamic language feature often placed in the +load method due to its early execution timing. The article analyzes how hook order and different swizzling schemes affect the final method call sequence when both a subclass and its superclass hook the same method.

Method Swizzling Common Implementation Schemes

Two typical schemes are discussed. Scheme A adds the original selector if it does not exist, then swaps implementations; Scheme B directly exchanges the IMPs.

Scheme A

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class aClass = [self class];

        SEL originalSelector = @selector(method_original:);
        SEL swizzledSelector = @selector(method_swizzle:);

        Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector);
        BOOL didAddMethod =
        class_addMethod(aClass,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));
        if (didAddMethod) {
            class_replaceMethod(aClass,
                               swizzledSelector,
                               method_getImplementation(originalMethod),
                               method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

A static‑method version is also shown, which avoids selector conflicts and _cmd tampering; CaptainHook adopts this approach.

typedef IMP *IMPPointer;

static void MethodSwizzle(id self, SEL _cmd, id arg1);
static void (*MethodOriginal)(id self, SEL _cmd, id arg1);

static void MethodSwizzle(id self, SEL _cmd, id arg1) {
    // do custom work
    MethodOriginal(self, _cmd, arg1);
}

BOOL class_swizzleMethodAndStore(Class class, SEL original, IMP replacement, IMPPointer store) {
    IMP imp = NULL;
    Method method = class_getInstanceMethod(class, original);
    if (method) {
        const char *type = method_getTypeEncoding(method);
        imp = class_replaceMethod(class, original, replacement, type);
        if (!imp) {
            imp = method_getImplementation(method);
        }
    }
    if (imp && store) { *store = imp; }
    return (imp != NULL);
}

+ (BOOL)swizzle:(SEL)original with:(IMP)replacement store:(IMPPointer)store {
    return class_swizzleMethodAndStore(self, original, replacement, store);
}

+ (void)load {
    [self swizzle:@selector(originalMethod:) with:(IMP)MethodSwizzle store:(IMPPointer *)&MethodOriginal];
}

Scheme B is a simplified version of Scheme A that directly exchanges IMPs.

Scheme B

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class aClass = [self class];

        SEL originalSelector = @selector(method_original:);
        SEL swizzledSelector = @selector(method_swizzle:);

        Method originalMethod = class_getInstanceMethod(aClass, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector);
       method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

Directly swapping IMPs can be dangerous when the class does not implement the method, as it may unintentionally replace a superclass implementation and cause crashes.

Research Background

Three classes: Child inherits Super , which inherits Base .

Both Child and Super hook the same method.

Original and swizzled selectors are named Child_Original , Child_Swizzle , etc.

Desired execution order for Child object: Child_Swizzle → Child_Original → Super_Swizzle → Super_Original → Base , abbreviated as Child → Super → Base .

The analysis enumerates 18 cases based on hook order, class implementation status, and scheme (A/B).

Diagrams (omitted) illustrate selector, method, and IMP mappings for each case.

Hook Order: Child First, Super Later

When the child class is hooked before the superclass, various combinations of implementation status and schemes produce different results, ranging from correct execution to unrecognized selector crashes or infinite loops. The article details each scenario (e.g., Super Plan A / Child Plan A, Super Plan B / Child Plan A, etc.) and lists the resulting method call chains for Child , Super , and Base objects.

Hook Order: Super First, Child Later

Even with the seemingly safer super‑first order, the same pitfalls exist if selectors clash or if a class does not implement the hooked method. The article again enumerates all combinations and describes the resulting call sequences and potential crashes.

Conclusion

Hook Order: Child → Super

The child class must implement the hooked method.

Swizzle helper methods in child and super must have distinct names.

The super class must either implement the hooked method or use Scheme A.

Hook Order: Super → Child

Swizzle helper methods in both classes must have distinct names.

Each class must implement the hooked method or use Scheme A.

Objective‑C Method Swizzling Best Practices

Hook order alone does not guarantee correctness; super‑first is generally safer.

When both parent and child hook the same method, ensure unique swizzle method names to avoid logic errors or dead loops.

Scheme A is preferable to Scheme B; its static‑method variant is more robust despite added complexity.

RSSwizzle solves many edge‑case issues but adds overhead; use it only for extreme cases.

jrswizzle offers better cross‑platform compatibility for low‑version systems.

Choose the approach that best fits the project’s needs.

mobile developmentiOSHookObjective-CMethod Swizzling
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.