3. Obj-C Pros, Cons, and Swift

Since 2014, Swift is the primary language for Apple platform development, but Objective-C is still important; probably more important if you’re reading this page since you’re probably focusing on macOS internals. Source for this section.

So, the benefits of Objective-C…

Dynamic runtime and flexibility

Objective-C is dynamic. It allows runtime method lookup and swapping (method swizzling), adding classes or methods at runtime, performing reflection (e.g., examining classes, methods, ivars at runtime), and forwarding messages to other objects.

This dynamism enables certain patterns that are harder in Swift, such as aspect-oriented* programming, method swizzling for logging or mocking, or dynamic proxy objects.*


* Aspect-oriented programming (AOP) is a paradigm that enables modularization of cross-cutting concerns—like logging, security, or error handling—by allowing behavior to be added to code dynamically without modifying the actual “business logic.”

* Dynamic proxy objects are runtime-generated objects that act as intermediaries, intercepting and forwarding method calls to target objects or handling them dynamically. These are often used for logging, delegation, and access control.


For example, categories (extensions) in Objective-C can add methods to classes at runtime, and the message dispatch system can be manipulated. As a non-software developer, (I think) these are pretty good tools for experienced developers and for certain frameworks.

Interoperability with C/C++

Objective-C being a superset of C means you can directly include and work with C code and libraries. There’s also Objective-C++ (.mm files) which allows mixing C++ and Objective-C in the same source. This is useful for projects that incorporate C++ libraries or low-level code. Swift can interface with C easily, but C++ interoperability is limited (Swift cannot directly call C++ methods without a bridging layer). Thus, Objective-C or Obj-C++ is often the glue for C++ code in Apple platforms.

Mature ecosystem and legacy code

We should know at this point that Objective-C has been the backbone of macOS and iOS for decades. There is a vast amount of existing code and documentation. Many older or lower-level APIs are still in Objective-C.

For maintenance of large, existing apps, Objective-C is almost always relevant. Apple’s system frameworks internally still use a lot of Objective-C (even if surfaced to Swift via bridges). Tools like nil messaging (sending a message to nil is a no-op in Objective-C) can sometimes simplify logic (though it can also hide bugs).

Stability and performance

Objective-C’s performance for most tasks is on par with Swift. Both call into the same Cocoa frameworks. In some cases, Objective-C’s dynamic dispatch may be slightly slower than Swift’s static dispatch, but with Objective-C runtime improvements, message sending is optimized (including caches). ARC in Objective-C has very low overhead. Also, compile-times for Objective-C are generally faster than large Swift projects (Swift’s type inference and generic system can introduce long compile times). This can make incremental builds in large Obj-C apps faster.

Swift UI/Combine Interop

While SwiftUI and Combine are Swift-only frameworks, you can still use them in an Obj-C app by adding some Swift glue. Conversely, UIKit/AppKit are Objective-C based, and Swift interfaces with them but sometimes the Objective-C APIs are more verbose in Swift. I saw on YouTube though that some developers prefer using certain UIKit features in Objective-C where the syntax might be simpler (though this is subjective).

Drawbacks of Obj-C

Syntax and ergonomics (because we only sit in Herman Miller chairs)

Objective-C’s syntax is verbose and dated. Message sends bracket notation ([object doSomething:arg]) and header files can feel cumbersome, and look scary and complicated.

Swift has a succinctsyntax (with type inference, generics, optionals, etc.); kinda reminds me of Python in that is almost seems to focus on being readable and clean. Many find Swift code more readable and easier to maintain, whereas Obj-C can appear cryptic (especially with its use of pointers, manual memory phrases, etc.). Additionally, Objective-C lacks namespacing; all classes live in a flat global namespace, which is why we have prefixes like NS (references NextStep, which I have another section on) or custom two-letter prefixes to avoid name collisions. Swift modules, by contrast, provide implicit namespacing.

Safety and type system

Swift was designed with safety in mind: it has strict typing, optionals to handle nil safely, boundary checking on arrays, etc. Objective-C is more lax; it’s possible to send any message to any object (if it doesn’t recognize it, it crashes at runtime or uses forwarding). There is no compiler enforcement to stop you from, say, treating an NSArray like an NSDictionary (you’d just get a runtime error).

Objective-C’s generics (introduced later in ARC) are mostly compiler annotations and are not enforced at runtime. Also, things like nil messaging being a no-op can lead to logic bugs that are hard to trace (nothing happens instead of a crash, potentially masking an issue). Swift’s optionals and strict value types help catch many of these issues at compile time. In short, Objective-C is less memory-safe and type-safe than Swift, which can lead (and almost always does) to bugs.

Memory management complexity

While ARC removed most of this burden, Objective-C still allows non-ARC code and needs understanding of pointers. In Swift, memory is largely managed (ARC for classes and value semantics for structs/enums) without exposing pointers except via UnsafePointer.

In Obj-C, you still deal with pointers explicitly (NSString *) and things like pointer arithmetic or C buffers when needed; it is actually similar to C from that standpoint I think. There’s also no automatic memory safety against things like buffer overruns or use-after-free if you drop down to C.

Swift, by default, makes these operations safer (or at least more apparent when you use Unsafe* APIs). Also, ARC in Swift handles more cases (e.g., it manages CoreFoundation objects through toll-free bridging seamlessly in many cases), whereas in Obj-C you might need to be more explicit.

Lack of hip and cool language features

Swift has value types (structs/enums) with copy semantics, pattern matching, generics that are enforced, protocol-oriented programming* enhancements, async/await concurrency model (there is entire books on Swift’s concurrency model btw), etc.


* Protocol-oriented programming is a paradigm that emphasizes defining behavior through protocols (interfaces) and composing functionality via protocol extensions, promoting flexibility, reuse, and type safety, especially in Swift.


Objective-C is object-oriented and class-based, but doesn’t have language-level support for concepts like concurrency primitives (Obj-C uses Grand Central Dispatch and completion blocks, which work in Swift too, but now Swift has async/await as language syntax).

Over time, Apple is obvi adding new capabilities primarily to Swift. For example, SwiftUI (for UI development), Combine (reactive programming), and many new frameworks are Swift-first and sometimes Swift-only. An Obj-C project cannot use SwiftUI without adding some Swift code. Thus, staying in Objective-C may limit access to some of these new frameworks or require extra workarounds.

Community and resources

The momentum in tutorials, sample code, and community libraries has shifted heavily to Swift; just checkout the Swift playground–there are lessons for toddlers in there! A new iOS developer in 2025 is likely to learn Swift first. This means finding help or up-to-date third-party libraries in Obj-C is harder (though many popular libraries from the 2010s are Obj-C and still usable). For long-term viability, I think it is fair to consider porting components to Swift.

Also, Apple’s WWDC demos and documentation are Swift-centric. Thus, I would think Objective-C developers have to mentally translate Swift code back into Obj-C, which would be non-trivial for newer features.

I need to go back and watch all the WWDC videos but I feel like I have not even heard official powerful Apple people say the phrase “Objective C” in a long long long time.

Mixing with Swift

It’s possible to mix and match Swift and Objective-C in a project (using bridging headers and @objc annotations for Swift-to-ObjC exposure). However, doing so adds complexity. You have to maintain two languages and interoperability layers. Pure Swift projects avoid that. That said, I think Apple tries to ensure that Obj-C and Swift interop is as smooth as possible. You can gradually migrate an app: for instance, write new features in Swift while existing Obj-C code remains; the two can call each other as needed. Apple isn’t deprecating Objective-C (the platforms still rely on it), but most new API surface is designed with Swift in mind.

In summary, Objective-C’s strengths lie in its dynamic capabilities, C/C++ friendliness, and the fact that it’s been around for decades. For some low-level tasks or legacy projects, it’s indispensable. However, for starting new projects, Swift links to fewer bugs (thanks to safety features), and access to modern APIs. Even Apple’s own security improvements (like rewriting iMessage parsing in Swift for memory safety) highlight the advantages of Swift’s safety. As one [analysis](sam-solutions.com put it, Swift “has borrowed positive features from Objective-C and C++ and abandoned outdated and complex elements” of Obj-C.

Again, Objective-C knowledge is important for understanding the inner workings of Apple’s OS-es and for maintaining Cocoa code. Many apps in the App Store use a mix of both languages.

Note on performance

It’s sometimes perceived that Swift is faster (due to modern optimizations) or that Objective-C is faster (due to its simpler runtime for certain tasks), but in practice both are high-performance. Swift can outperform Obj-C in tight loops because it can avoid dynamic dispatch (or use C-like structs), but Objective-C’s performance is more than adequate for typical app demands. Apple has locked down Swift’s ABI. The choice is more about safety and developer productivity than raw speed. And if ultimate speed is needed, one can always drop to C/Metal/Accelerate regardless of using Swift or Obj-C.