Objective-C is a general-purpose programming language that combines the C programming language with object-oriented messaging and runtime features derived from Smalltalk. It was created in the early 1980s by Brad Cox and Tom Love, with Cox's work on extending C with object-oriented capabilities forming a major part of its development.
The language became particularly significant through NeXT and later Apple, where it served as a principal programming language for NeXTSTEP, OPENSTEP and Apple's Mac OS X and iOS software ecosystems for many years. Objective-C retains C as a genuine foundation, so C source code can generally be incorporated into Objective-C programs, while additional syntax provides classes, objects, methods, protocols, categories and dynamic runtime behaviour.
Its object model is message-oriented rather than based solely on the conventional C++ model of direct method invocation and compile-time class relationships. Objective-C therefore occupies a distinctive position in programming-language history: it helped bring Smalltalk-inspired dynamic object-oriented programming to systems programming environments based on C and became deeply embedded in Apple's software frameworks before Swift became Apple's newer primary language for application development.
The central conceptual distinction in Objective-C is between sending a message to an object and directly invoking a statically resolved method in the C or C++ sense. Square-bracket syntax is used for message expressions, such as sending a message to an object. The runtime determines the appropriate method implementation using the object's class and method dispatch mechanisms. Objective-C supports both statically typed declarations and considerable dynamic behaviour, allowing objects to be inspected, modified or messaged at runtime.
The language defines special values such as nil for an absent object reference and provides mechanisms for checking whether objects respond to particular selectors. Selectors represent method names in the runtime system and can be manipulated as data. This dynamic model supports techniques such as runtime introspection, method swizzling and dynamic method resolution, although some of these mechanisms can make code harder to analyse or maintain. The messaging model also explains why Objective-C method calls have historically been associated with runtime overhead compared with direct C function calls, although compiler optimisations and modern runtimes can reduce that cost in many situations.
Objective-C classes are declared and implemented using constructs such as @interface and @implementation. A class can inherit from a superclass and define instance variables, properties and methods. Methods are commonly categorised as instance methods or class methods, with a leading minus or plus sign respectively in declarations. Properties provide a higher-level way of declaring accessors and can specify ownership and memory-management attributes.
Objective-C also supports categories, which allow methods to be added to an existing class without modifying its original source declaration or creating a subclass. Extensions provide a related mechanism for declaring additional implementation details, often used to keep private interfaces out of public headers. Protocols define collections of methods that classes or objects can adopt, functioning somewhat like interfaces in other object-oriented languages. These constructs allow Objective-C to support inheritance, composition, behavioural contracts and modular extension while retaining the language's dynamic runtime. Categories are particularly important in Cocoa and Cocoa Touch development because they provide a mechanism for separating functionality into logically organised units.
Memory management has been an important part of Objective-C's evolution. Early Objective-C environments commonly relied on manual reference counting, in which objects maintained reference counts and programmers explicitly retained and released objects. Apple's introduction of Automatic Reference Counting, or ARC, moved much of this bookkeeping into the compiler, which inserts appropriate ownership-management operations while preserving deterministic reference-counting semantics.
Objective-C also has autorelease pools, which allow objects to be scheduled for later release and are particularly important when large numbers of temporary objects are created. The language's modern memory model therefore differs from tracing garbage-collected environments: ARC primarily manages object lifetime through ownership and reference counting rather than periodically tracing the entire object graph. Strong, weak, copy and unsafe-unretained property semantics distinguish different ownership relationships. Weak references are particularly important for avoiding retain cycles in object graphs, such as those involving delegates or parent-child relationships. Developers must still understand object ownership, lifetime and cycles because automatic reference counting does not make all memory-management errors impossible.
Objective-C became closely associated with Apple's Foundation, Cocoa and Cocoa Touch frameworks. Foundation supplies classes and utilities for strings, collections, dates, data, networking and other general application functions, while higher-level frameworks historically used Objective-C as their principal interface language. UIKit provided the application and user-interface framework for iOS and related platforms, while AppKit served macOS desktop applications.
Objective-C headers also expose many framework APIs in forms that can be consumed by Swift, and Apple's interoperability mechanisms have allowed large Objective-C codebases to coexist with newer Swift code. The language's C foundation provides direct access to low-level APIs and enables interoperability with C libraries. Objective-C can also interact with C++ through Objective-C++, which uses .mm source files and permits Objective-C and C++ constructs to coexist. This has been useful for applications that combine Apple frameworks with existing C++ engines, libraries or performance-sensitive components. Consequently, Objective-C's practical significance extends beyond its syntax because it became an interface layer between low-level C-based software and dynamic object-oriented application frameworks.
Objective-C's runtime is a major source of its distinctive capabilities. The runtime maintains information about classes, methods, selectors and objects and provides mechanisms for dynamic dispatch, introspection and class manipulation. Runtime functions can obtain class metadata, inspect method lists, create instances and perform other operations that would be more constrained in a purely static language. The runtime also supports associated objects, which can attach additional data to objects without changing their original class definition.
Key-value coding and key-value observing, historically important in Apple's frameworks, further reflected Objective-C's dynamic design. The language's dynamism enabled sophisticated framework patterns but also introduced risks: a selector can be syntactically valid yet fail at runtime if an object does not implement the expected method, and extensive runtime modification can complicate debugging. Modern Objective-C development commonly combines compiler checking, nullability annotations, generics for collections and static analysis with the dynamic runtime, producing a balance between compile-time safety and runtime flexibility.
Objective-C's historical role is closely tied to the evolution of Apple's software platforms. NeXT adopted Objective-C as part of its development environment, and when Apple acquired NeXT, the technology became foundational to Mac OS X. The subsequent rise of the iPhone and iOS created a vast Objective-C developer ecosystem, with applications and frameworks commonly written in Objective-C for much of the first decade of iOS development.
Apple introduced Swift in 2014 as a newer programming language designed to provide modern syntax and stronger compile-time safety while integrating with existing Apple frameworks. Swift did not make Objective-C immediately obsolete because enormous existing codebases, frameworks and libraries remained in active use and interoperability was deliberately supported. Objective-C therefore continues to appear in legacy and modern mixed-language Apple projects even though Swift has become central to new development. Its historical importance also extends to language design because it demonstrates how dynamic object-oriented features can be layered onto a systems language without abandoning the underlying C environment.
Objective-C's strengths include direct C interoperability, a mature runtime, powerful dynamic dispatch, an extensive historical Apple framework ecosystem and the ability to integrate gradually with existing C-based software. Its limitations include comparatively verbose and unusual syntax, runtime errors that can arise from dynamic messaging, complicated historical memory-management practices, and a reduced role in new Apple application development relative to Swift.
Objective-C should not be confused with C++, despite both extending C with object-oriented facilities: their object models, syntax, runtime assumptions and design histories are substantially different. It also should not be treated as merely "C with classes", because its message-passing model and runtime metadata give it capabilities that are conceptually closer to Smalltalk-style dynamic object orientation. Its significance today is therefore partly practical and partly historical. It remains relevant when maintaining existing Apple software, interfacing with Objective-C frameworks, working with mixed Objective-C and Swift codebases, or understanding the foundations of Apple's older development ecosystem, while its design remains an important example of dynamic object-oriented programming integrated into a systems-language environment.