Skip to content

Languages

Objective-C

The language that built the Apple ecosystem for decades — kept running, mixed with Swift, and migrated one file at a time by engineers who have done it before.

Overview

Objective-C is the language Apple’s platforms were built on for the better part of thirty years. It is a strict superset of C, which means every line of C is valid Objective-C, with a layer of Smalltalk-style object orientation added on top: objects talk to each other by passing messages rather than calling methods directly, and that messaging happens through a dynamic runtime that resolves what to do at execution time rather than at compile time. Its distinctive bracket syntax — [object doSomethingWith:argument] — is that message send made visible. The Cocoa and Cocoa Touch frameworks that still underpin iOS and macOS were designed around this model, and categories, protocols and the runtime’s introspection gave the language a flexibility that shaped how Apple software was written for a generation.

We want to be plain about where Objective-C sits in 2026: it is a legacy-maintenance and interoperability concern, not a language anyone should choose for a new app. Apple has moved to Swift, invests in Swift, and points every new framework and API at Swift first. But moving on from a language and deleting the code written in it are very different things. Enormous amounts of shipping, revenue-generating Apple software — apps millions of people open every day — are still substantially Objective-C, and that code does not stop needing attention because a newer language exists. It needs bug fixes, it needs to keep working through each year’s OS release, it needs security and dependency updates, and, where it makes sense, it needs to be moved to Swift gradually rather than gambled on a rewrite.

That last point is the heart of how we use Objective-C. The two languages interoperate cleanly inside a single codebase — a Swift class can call Objective-C and vice versa through a bridging header — so the realistic path for a mature app is not "rewrite in Swift" but "add Swift alongside, migrate file by file, and delete Objective-C as it is replaced." We treat Objective-C as something to maintain competently and retire deliberately, on a schedule the business can afford, rather than something to either fear or preserve in amber.

Best for — Maintaining, stabilising and incrementally migrating existing Objective-C iOS and macOS apps — and running mixed Objective-C/Swift codebases — not starting anything new.

Why teams choose Objective-C

  • Your existing app keeps earning

    The code that already ships and already makes money does not have to be rewritten to have a future. Competent maintenance keeps an Objective-C app compatible, stable and secure through OS releases, buying you time to migrate on your own terms rather than under emergency pressure.

  • Migration without the rewrite risk

    Because Objective-C and Swift live together in one codebase, we move you to Swift incrementally — the app builds, tests and ships at every step. You avoid the classic rewrite failure mode, where a parallel Swift version consumes the budget and never catches up to the features the old app already had.

  • The code gets genuinely read

    Old Objective-C often does surprising things through the dynamic runtime, categories and pre-ARC memory patterns. We read it properly before we touch it, so changes are made with an understanding of what the code was actually doing — not by guessing and hoping the crash reports stay quiet.

Why businesses choose Objective-C

  • You have a real, shipping Objective-C app and you need it maintained properly — not rewritten, not abandoned, but kept stable and compatible while it still earns.
  • You want to migrate to Swift but cannot afford the risk or downtime of a rewrite, and need someone who can do it incrementally with the app live throughout.
  • You value engineers who will read pre-ARC memory code and runtime tricks correctly before changing them, rather than juniors learning the language on your production app.
  • You would rather be told honestly that a new app should be Swift, and pointed at the right tool, than sold Objective-C work that does not serve you.

What we build with Objective-C

The capabilities this technology is genuinely strong at — and what we most often build with it.

  • Dynamic runtime and message passing

    Objective-C dispatches by sending messages through a runtime that resolves them at execution time, which is why introspection, dynamic method resolution and forwarding are possible at all. We understand this model in depth — including that a message to nil is a silent no-op, one of the language’s most common sources of a bug that never announces itself — and we work with it deliberately rather than being surprised by it.

  • Categories and method swizzling

    Categories let you add methods to existing classes without subclassing, and the runtime lets you swap method implementations at load time — swizzling. These are powerful and heavily used in older codebases, and also a classic source of action-at-a-distance bugs. We map where a codebase uses them before we change anything, because a category or a swizzle in one file can quietly alter behaviour in another.

  • ARC and pre-ARC memory management

    Automatic Reference Counting removed most manual retain and release calls, but a great deal of long-lived Objective-C predates it or mixes the two, and retain cycles still leak under ARC. We are fluent in both worlds — reading manual retain/release code correctly, and using weak and strong references and autorelease pools properly under ARC.

  • Bridging headers and Swift interop

    The bridging header is the seam where Objective-C and Swift meet in one app. We manage it carefully — exposing the right Objective-C interfaces to Swift, annotating nullability and generics so the Swift side sees sane types rather than implicitly-unwrapped optionals everywhere, and keeping the boundary clean as code migrates across it.

  • Cocoa and Cocoa Touch fluency

    The frameworks under iOS and macOS — UIKit, AppKit, Foundation and the rest — were designed around Objective-C idioms like delegation, target-action and key-value observing. Maintaining an Objective-C app means knowing these patterns as they were actually used, including the older conventions that predate today’s Swift-first documentation.

  • Incremental Swift migration

    The distinctive thing we build with Objective-C is a way out of it. We migrate file by file and module by module — replacing an Objective-C class with a Swift one, wiring it back through the bridging header, keeping tests green and the app shippable at every commit — so the codebase is always releasable and the Objective-C shrinks steadily instead of being frozen or gambled.

Use cases

  • Maintaining a shipping legacy app

    A mature Objective-C iOS or macOS app that still serves users and makes money, needing bug fixes, crash reduction, and the yearly work of staying compatible when a new OS deprecates an API or changes behaviour underneath it.

  • OS-compatibility rescue

    An app that has fallen behind — building against an old SDK, tripping deprecation warnings, or breaking on the latest iOS or macOS — brought back to a clean, releasable state before it stops working in the store altogether.

  • Mixed Objective-C and Swift codebase

    An app that is part-migrated, with new features in Swift and a large Objective-C core, where the two need to coexist cleanly and the boundary between them needs to be maintained by someone who understands both sides.

  • Incremental migration to Swift

    A deliberate, funded effort to move an Objective-C app to Swift over time — file by file, with the app live and releasing throughout — instead of a rewrite that risks the product and the schedule.

When Objective-C is the right choice

  • You have an existing Objective-C iOS or macOS app that earns money and needs to keep working — bug fixes, crash reduction, and the annual round of OS-compatibility updates when a new iOS or macOS release breaks or deprecates something you depend on.
  • You run a mixed Objective-C and Swift codebase and want new work done in Swift without disturbing the older code that still ships every day. The two interoperate through a bridging header, and knowing exactly where that seam sits is most of the job.
  • You want to migrate off Objective-C incrementally — file by file, module by module, with the app working and releasing throughout — rather than betting the product on a big-bang rewrite that stalls, misses features the old code quietly had, and ships regressions.
  • You need someone who can actually read the code. A lot of Objective-C was written before ARC, leans on the dynamic runtime in clever ways, or hides behaviour in categories and swizzling — and reading it correctly before you change it is a skill the talent pool is steadily losing.
  • Wrong for: a new app. Nobody should start a greenfield iOS or macOS product in Objective-C in 2026 — it is more verbose, more error-prone, and lacks Swift’s safety. If that is what you are here for, we will point you at our Swift and iOS pages and talk you out of it before you write a line.

Objective-C: pros and cons

Strengths

  • Rock-solid interoperability with Swift: the two languages share a runtime and call each other cleanly, which is precisely what makes gradual migration possible instead of forcing an all-or-nothing rewrite.
  • A mature, battle-tested foundation: the Cocoa and Cocoa Touch frameworks and the C underpinnings have been hardened over decades, and vast, dependable systems are built on them.
  • Genuine runtime dynamism: message passing, introspection and categories allow patterns — method swizzling, flexible dispatch, runtime configuration — that a statically dispatched language makes harder, which is occasionally exactly what a problem needs.
  • Direct, unmediated access to C: because it is a superset of C, Objective-C drops down to C and C++ libraries with no bridge, which matters for the older media, cryptography and systems code that many long-lived apps still rely on.

Trade-offs

  • It lacks Swift’s modern safety. No optionals, no value types, weak compile-time checking — a message to nil silently does nothing, and whole categories of bug that Swift catches at compile time only surface at runtime in Objective-C.
  • It is verbose and more error-prone. The bracket syntax, manual header and implementation files, and pointer-heavy idioms mean more code and more places to make a mistake than the equivalent Swift.
  • The talent pool is ageing and shrinking. Fewer engineers learn Objective-C now, and the ones who know it deeply are moving on — which makes both hiring and long-term maintenance harder every year, and is itself an argument for migrating.
  • It is a dead end for new work. Apple’s investment, its newest frameworks, and every modern API design point at Swift first. Staying in Objective-C means steadily drifting away from where the platform is going.

Architecture

Most Objective-C apps we take on were architected in an earlier era, typically around Model-View-Controller as Cocoa Touch encouraged it, with delegation, target-action and key-value observing wiring the parts together. Before we change anything, we map that architecture as it actually is — where the runtime is leaned on, where categories and swizzling alter behaviour, where memory is managed manually versus under ARC — because in a long-lived codebase the real structure is rarely the one the original documentation describes, if any documentation survives at all.

When the work is migration, the architecture goal is a clean, well-defined seam between the Objective-C that remains and the Swift that replaces it. We identify modules that can be lifted across whole, expose the Objective-C the Swift side needs through a properly annotated bridging header, and keep the boundary narrow so the two languages meet in as few, as well-understood places as possible. The aim is a codebase that is always coherent and always shippable, shrinking on the Objective-C side release by release, rather than two half-finished apps sharing a repository.

Performance

Objective-C is fast: it compiles to native code and drops straight to C, so raw throughput is rarely the problem. The overhead people cite — the indirection of dynamic message dispatch — is real but small, and almost never what actually makes an app feel slow. As with any Apple-platform app, perceived performance is decided on the main thread: work that should be off it, layout that thrashes, or oversized caches will stutter an interface regardless of language, and that is where we profile with Instruments rather than guessing.

The performance risk specific to older Objective-C is memory. Pre-ARC code with manual retain and release, or ARC code with retain cycles, will leak and grow an app until the system kills it, and legacy image and data handling is a frequent culprit. We watch allocations, break cycles with weak references, and are honest that keeping a decade-old app fast through a long session on a real device is a maintenance discipline, not a one-off fix — which is exactly the standard we hold the work to.

Security

The security work on an Objective-C app is mostly about the platform and the dependencies, not the language. We store credentials and tokens in the Keychain rather than in preferences or plain files, enforce App Transport Security so traffic is encrypted, and keep authorisation decisions on the server where the client cannot be trusted to make them. In older apps a common finding is code that predates these expectations — plaintext storage, disabled ATS exceptions left in for convenience, secrets in the binary — and part of maintenance is quietly closing those gaps.

Because Objective-C is a superset of C, it also inherits C’s memory-safety pitfalls in a way Swift does not: buffer handling, pointer arithmetic and manual memory in older code are places where real vulnerabilities live, and we treat that C-level surface with the caution it deserves. We also keep an eye on ageing third-party libraries, many of which are themselves unmaintained Objective-C, since an out-of-date dependency is often the most exposed part of a legacy app.

Scalability

For a client app the scaling question is not request load — the backend carries that — but whether the codebase and the people who maintain it can keep going. This is where Objective-C’s honest weakness shows: the pool of engineers who can work in it confidently is shrinking, so a large, Objective-C-only codebase becomes harder and more expensive to staff every year. Scalability, for these apps, largely means reducing that exposure over time.

That is why we treat incremental migration to Swift as the real scalability strategy rather than an optional nicety. Moving the codebase to Swift, module by module, widens the pool of engineers who can maintain it, brings back compile-time safety that makes change less risky, and keeps the app aligned with where Apple is taking the platform. We plan that migration so it can pause and resume around the business’s priorities — the app stays shippable throughout, and the Objective-C footprint gets smaller with each release instead of calcifying.

Objective-C integrations & ecosystem

The technologies we most often pair with it — each links to how we work with it.

How we work

We start by reading the code and the crash reports, not by proposing a rewrite. For a maintenance engagement that means understanding what the app actually does — where the runtime is leaned on, where memory is managed manually, where the OS-compatibility risks sit — and stabilising the load-bearing paths first. For a migration it means agreeing a route: which modules move to Swift, in what order, and how we keep the app building, testing and shipping at every step through the bridging header rather than forking a parallel version.

The engineers who assess your app are the ones who do the work and keep it running through OS releases and store reviews — that is what we mean by operating what we build. It also means we will tell you the unwelcome truths: when a chunk of Objective-C is not worth migrating yet, when a rewrite genuinely is the lesser risk, and above all that a new app should be Swift, not this. You get honest senior judgement about a language most of the industry has moved past but a lot of important software still runs on.

The service behind it

Delivered throughCustom Software Development

What we build with Objective-C

The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.

How we deliver

  1. 01

    Discover

    We map the system, the constraints and the business it serves — including the parts nobody documented.

    Architecture brief

  2. 02

    Architect

    Decisions get made, written down and defended before a line of production code exists.

    Decision records

  3. 03

    Build

    Short cycles against working software. You see progress in the product, not in a status deck.

    Shipping increments

  4. 04

    Operate

    Monitoring, incident response and iteration. The system is alive, so the engagement is too.

    Runbooks & SLOs

Industries we use Objective-C in

Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.

Also in Languages

Why teams choose us for Objective-C

  • We can actually read it

    Pre-ARC memory code, runtime message forwarding, categories and swizzling are things you learn by having worked in Objective-C, not by skimming it. The engineers on your app have shipped Objective-C, and there are no juniors learning a legacy language on your production code.

  • We operate what we build

    We keep apps running through OS updates and store reviews, so we optimise for the maintenance reality of a long-lived codebase — conservative, well-understood changes over clever ones, and code your team can keep owning after we hand it back.

  • Migration, not rewrites

    We move you to Swift incrementally, with the app live and releasing at every step, because we have seen enough rewrites stall to know the risk. You get a shrinking Objective-C footprint on a schedule you can afford, not a gamble on a parallel version.

  • Honest about the language

    We will tell you plainly that no new app should be built in Objective-C, and point you at Swift and our iOS work instead. We would rather steer you right than take Objective-C work that does not serve you.

Typical timeline

  1. 01

    Assessment and read-in

    One to two weeks reading the codebase and crash data — mapping the architecture, the runtime and category usage, the memory model, and the OS-compatibility risks — so any plan is based on what the app actually is, not a guess.

  2. 02

    Stabilise the load-bearing paths

    Fixing the crashes and compatibility breaks that matter first, getting the app building cleanly against a current SDK and releasing reliably, before any larger change is contemplated.

  3. 03

    Incremental migration or ongoing maintenance

    Either steady maintenance through OS releases, or file-by-file migration to Swift through the bridging header — each step keeping the app tested and shippable, the Objective-C footprint shrinking release by release.

  4. 04

    Handover and documentation

    Documenting the runtime tricks, the migration state and the maintenance realities so your team — or the next engineers — can pick the app up without relearning it from crash reports.

How pricing works

  • Monthly senior engagement for ongoing maintenance — bug fixes, crash reduction, OS-compatibility updates and dependency upkeep on a shipping Objective-C app — where the work is continuous and you want continuity through each year’s OS cycle.
  • Fixed-scope migration phases, each a defined set of modules moved from Objective-C to Swift with the app shippable at the end, so you can fund the migration in affordable increments rather than one open-ended commitment.
  • Focused audits and rescues — a compatibility rescue for an app breaking on the latest OS, a crash-rate or memory-leak investigation, or an assessment of what migrating would actually take — priced by the piece of work.

Hire Objective-C engineers

Need Objective-C capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.

Hire Objective-C engineers

Common questions

Should we rewrite our Objective-C app in Swift?

Almost never as a big-bang rewrite — that is the failure mode we most want to keep you out of. Because Objective-C and Swift share a runtime and interoperate through a bridging header, the far safer path is incremental migration: replace the code file by file and module by module, with the app building, testing and shipping at every step. A parallel Swift rewrite tends to consume the budget while quietly missing features the old app already had. We migrate; we do not gamble the product on a restart.

Is it worth migrating off Objective-C at all, or can we just maintain it?

Both can be right, and it depends on how long the app needs to live and how much it will change. If it is stable and barely touched, competent maintenance may be all it needs for years. But the talent pool is shrinking and Apple’s investment is entirely in Swift, so a codebase that keeps growing in Objective-C gets harder and more expensive to staff over time. For an app under active development, incremental migration is usually the sound long-term call — we will give you an honest read on which side of that line yours sits.

Our app breaks on the latest iOS — can you fix it without rewriting?

Yes, and that is one of the most common jobs we do. OS-compatibility breaks are usually a matter of deprecated APIs, changed behaviour or building against an outdated SDK, all of which can be fixed within the existing Objective-C. We get the app building cleanly against a current SDK and releasing reliably again first — the rescue is a maintenance job, not a reason to throw the codebase away.

Would you build a new app in Objective-C?

No. Nobody should start a new iOS or macOS app in Objective-C in 2026 — it is more verbose, more error-prone, lacks Swift’s compile-time safety, and draws on a shrinking pool of engineers. If you are considering it, we will talk you out of it and point you at Swift and our iOS work. Objective-C is a language we maintain and migrate away from, not one we would start anything new in.

Can you work in a codebase that is already part Objective-C and part Swift?

Yes — mixed codebases are the normal state of a migrating app, and managing the boundary between the two is a core part of what we do. We keep the bridging header clean, annotate the Objective-C so the Swift side sees sensible types rather than implicitly-unwrapped optionals everywhere, and add new work in Swift without disturbing the older code that still ships. Knowing exactly where the seam sits is most of doing this well.

Building on Objective-C?

A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.

Two fields required. We reply to real enquiries — no list, no sequence.