🍫 CocoaPatterns — iOS & Mac Development Since 2009 RSS
🍫 CocoaPatterns
Because someone has to write this stuff down
"We ship apps. Sometimes they even work."

Swizzle-Driven Development: The Objective-C Architecture Pattern You Didn't Know You Needed

Move over MVC, MVVM, and VIPER. The future of iOS architecture is already baked into the runtime.

BK
Brad Kowalski
@bradkow_ios · CocoaPatterns

I've been writing Objective-C since the iPhone OS 2.1 days. I've watched the community swing from MVC to MVVM, flirt with ReactiveCocoa, and now apparently everyone is in love with something called VIPER which, as far as I can tell, is just MVC but with more files and a cooler name.

But today I want to talk about something different. Something that's been hiding in plain sight since NeXT workstations were cool. Something the Objective-C runtime has given us all along that we've been criminally underusing as an architectural foundation.

I'm talking about Swizzle-Driven Development, or SDD.

"If you're not swizzling, you're not really doing Objective-C. You're just writing Java with square brackets."

What Is Swizzle-Driven Development?

The core thesis is simple: the best architecture is one where you never have to change the original code. Instead, you intercept, augment, and replace behavior at runtime using method swizzling. Think of it as aspect-oriented programming, but instead of build-time weaving, you do it at +load time. Dynamically. In production.

The key insight is that in SDD, your entire application logic layer lives in categories full of swizzled methods. Your original classes remain pristine. Untouched. The business logic simply... wraps around them like a loving, imperceptible embrace.

💡 Key Principle

In SDD, the golden rule is: touch nothing, change everything. Every behavior modification flows through the runtime, not the source. Your original source files become sacred artifacts, read-only monuments to your original intent.

The Core Building Block

Drop this in a category on NSObject — yes, NSObject, why would you put it anywhere else — and you're off to the races:

@implementation NSObject (SDD)
+ (void)swizzleMethod:(SEL)original withMethod:(SEL)swizzled {
    Method originalMethod = class_getInstanceMethod(self, original);
    Method swizzledMethod = class_getInstanceMethod(self, swizzled);
    // This is fine. This is always fine.
    method_exchangeImplementations(originalMethod, swizzledMethod);
}
@end

Beautiful. Now let's build an architecture on top of it.

The SDD Application Layer

In traditional MVC, your view controllers become massive 3,000-line behemoths. In SDD, there are no bloated view controllers. There's just +load.

@implementation UserProfileViewController (SDD)
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleMethod:@selector(viewDidLoad)
             withMethod:@selector(sdd_viewDidLoad)];
        [self swizzleMethod:@selector(purchaseButtonTapped:)
             withMethod:@selector(sdd_purchaseButtonTapped:)];
        // Swizzle dealloc for memory tracking
        // (This is controversial but I stand by it)
        [self swizzleMethod:@selector(dealloc)
             withMethod:@selector(sdd_dealloc)];
    });
}
- (void)sdd_viewDidLoad {
    [self sdd_viewDidLoad]; // This calls the original. Trust me.
    [[SDDAnalyticsEngine sharedEngine] trackScreen:@"UserProfile"];
}
// ... 847 more lines ...
@end
⚠️ Common Gotcha

New SDD practitioners are often confused by the recursive-looking call [self sdd_viewDidLoad] inside sdd_viewDidLoad. Don't worry — because of the swizzle, this actually calls the original viewDidLoad. This is not confusing at all once you fully internalize how swizzling works. It took me about six weeks.

Real-World Results

  • Original source files: 100% unchanged ✅
  • New SDD category files added: 847
  • Total swizzle invocations at app launch: ~2,300
  • Onboarding time for new engineers: we stopped hiring
  • Senior engineers who quit: not confirmed to be related

Now if you'll excuse me, I need to go swizzle UIApplication's sendEvent: to fix a bug that I introduced by swizzling UIApplication's sendEvent:.

5 Comments — Powered by Disqus
JH
jharrington_dev · 2 days ago
This is either genius or the most irresponsible thing I've read on this blog, and I'm including the Core Data encryption post from 2012.
BK
bradkow_iosAuthor · 2 days ago
@jharrington_dev I'll accept genius. We've had this in production for three months with zero confirmed SDD-related outages.
MV
mvermeer · 1 day ago
I showed this to my team and two of them sent me the Wikipedia article for 'technical debt' without comment.
DL
DaveLorimer_iOS · 18 hours ago
Brad, I am the Dave who left. I left because of this.
BK
bradkow_iosAuthor · 17 hours ago
@DaveLorimer_iOS Hey Dave. Hope you're doing well. The link order on the payment module is still your fault btw