Objective-C es un lenguaje de programación con despacho dinámico de mensajes, creado por Brad Cox en la década de 1980. Apple eligió Objective-C como lenguaje principal para NeXTSTEP y más tarde para el SDK de iOS. Programming With Objective-C — una introducción a la sintaxis de mensajes y la gestión de memoria.
Puntos clave
Objective-C es un lenguaje de programación que extiende C con capacidades de programación orientada a objetos al estilo Smalltalk. El código Objective-C se compila mediante LLVM o GCC en código máquina nativo, manteniendo total compatibilidad hacia atrás con C — cualquier código C es válido en Objective-C.
Apple adquirió NeXT (junto con Objective-C) en 1997. El lenguaje se convirtió en la base de Cocoa y Cocoa Touch — los frameworks para macOS e iOS. Desde 2014, Apple promueve Swift como reemplazo, pero Objective-C sigue siendo críticamente importante para proyectos heredados y algunos frameworks del sistema. Según Apple (WWDC 2024), alrededor del 35% de las aplicaciones en la App Store aún contienen código Objective-C.
La característica clave es el runtime dinámico. A diferencia de Swift, donde las llamadas a métodos se resuelven en tiempo de compilación, Objective-C envía mensajes en tiempo de ejecución a través de la función objc_msgSend. Esto permite sobrescribir métodos sobre la marcha (method swizzling), añadir clases dinámicamente y usar forward invocation para selectores inexistentes.
Cualquier código C es válido en Objective-C. La extensión orientada a objetos añade clases (@interface/@implementation), categorías, protocolos (@protocol) y tipado dinámico (id). Los archivos tienen extensiones .m (implementación) y .h (encabezados).
La sintaxis de mensajes es la principal diferencia entre Objective-C y los lenguajes similares a C. En lugar de object.method(argument), se utiliza [object method:argument]. Cada mensaje pasa a través de objc_msgSend, que busca dinámicamente la implementación del método en el runtime.
// Sintaxis de mensajes con parámetros nombrados
NSString *greeting = [NSString stringWithFormat:@"Hello, %@", name];
// Mensajes anidados
NSArray *sortedArray = [[array sortedArrayUsingSelector:@selector(compare:)] copy];
// Verificación de tipo mediante introspection
if ([object isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)object;
view.backgroundColor = [UIColor redColor];
}El despacho dinámico permite sobrescribir métodos en tiempo de ejecución (method swizzling) — una técnica potente pero peligrosa. Por ejemplo, frameworks como AFNetworking y Aspects utilizan swizzling para interceptar llamadas de URLSession. Apple advierte: el swizzling puede dañar los frameworks del sistema si se usa incorrectamente.
Las Categorías son una característica única de Objective-C que permite añadir métodos a clases existentes (incluyendo clases del sistema como NSString y UIView) sin herencia y sin acceso al código fuente. Las categorías se declaran mediante @interface ClassName (CategoryName).
// Archivo UIColor+Hex.h — categoría para UIColor
@interface UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex;
@end
// Archivo UIColor+Hex.m — implementación
@implementation UIColor (Hex)
+ (instancetype)colorWithHex:NSUIntegerhex {
CGFloat r = ((hex >> 16) & 0xFF) / 255.0;
CGFloat g = ((hex >> 8) & 0xFF) / 255.0;
CGFloat b = (hex & 0xFF) / 255.0;
return [self colorWithRed:r green:g blue:b alpha:1.0];
}
@endLas Extensiones (Class Extension) son un tipo especial de categoría declarada en un archivo .m sin nombre: @interface ClassName (). A diferencia de las categorías, las extensiones pueden añadir no solo métodos sino también ivar (variables de instancia) y propiedades. Las extensiones se utilizan para ocultar la API interna de los módulos externos.
Los Bloques son funciones anónimas en Objective-C que capturan variables del ámbito externo. Sintaxis de bloques: ^(int x) { return x * 2; }. Los bloques se utilizan en UIKit para manejadores de callback, en Grand Central Dispatch para tareas asíncronas y en colecciones NSArray/NSDictionary para operaciones funcionales.
// Declaración de tipo de bloque
typedef void (^CompletionBlock)(BOOL success, NSError *error);
// Bloque como parámetro
- (void)fetchDataWithCompletion:(CompletionBlock)completion {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL result = [weakSelf processData];
if (completion) {
completion(result, nil);
}
});
}La gestión de memoria en los bloques es críticamente importante. Los bloques capturan self con una referencia fuerte, creando un retain cycle cuando se usan directamente. La solución es __weak typeof(self) weakSelf = self, seguida de una verificación dentro del bloque. Este problema está completamente resuelto en Swift mediante capture lists [weak self].
Objective-C evolucionó de MRC (Manual Reference Counting) a ARC (Automatic Reference Counting). En MRC, el desarrollador llamaba manualmente a retain (incrementar contador), release (decrementar) y autorelease (liberación diferida). Los errores en estas llamadas provocaban fugas de memoria o crashes debido a punteros colgantes.
| Operación | MRC | ARC |
|---|---|---|
| Creación de objeto | [[Object alloc] init] | [[Object alloc] init] |
| Retención de referencia | [object retain] | Automáticamente |
| Liberación | [object release] | Automáticamente |
| Autoliberación | [object autorelease] | Automáticamente (no requerido) |
| Referencia débil | __weak no existía | __weak (nil automático) |
ARC se introdujo en Xcode 4.2 y LLVM 3.0 (2011). El compilador inserta automáticamente retain/release en tiempo de compilación analizando el ciclo de vida de los objetos. ARC no es recolección de basura — es análisis estático con inserciones automáticas. ARC de Objective-C es compatible con ARC de Swift: ambos usan el mismo sistema de recuento de referencias a nivel de runtime.
El uso conjunto de Objective-C y Swift en un mismo proyecto es una práctica común para proyectos heredados. Apple proporciona el Bridging Header — un archivo generado automáticamente a través del cual Swift ve las clases de Objective-C, y Objective-C ve las clases de Swift que heredan de NSObject.
// ProjectName-Bridging-Header.h
// Swift ve estos encabezados automáticamente
#import "LegacyManager.h"
#import "NetworkClient.h"
#import "DataStore.h"La migración de Objective-C a Swift es un proceso gradual. Los archivos nuevos se escriben en Swift, los antiguos se refactorizan gradualmente. El Bridging Header se genera automáticamente al añadir el primer archivo Swift a un proyecto Objective-C. Para la visibilidad inversa (ObjC → Swift), Xcode genera un archivo <ProjectName>-Swift.h que contiene declaraciones @interface para las clases Swift marcadas con @objc.
// Clase Swift visible desde Objective-C
@objc class SwiftRouter: NSObject {
@objc func navigateToProfile(userId: Int) {
// implementación
}
}Limitaciones: los tipos valor de Swift (struct, enum) no son visibles directamente desde Objective-C — deben envolverse en una clase con @objc. Los genéricos de Swift tienen accesibilidad limitada desde Objective-C. El enfoque recomendado es escribir código nuevo en Swift y refactorizar el código Objective-C existente solo al cambiar la funcionalidad correspondiente.
La principal ventaja de Objective-C sobre Swift es el acceso completo al runtime. El method swizzling, que reemplaza implementaciones de métodos en tiempo de ejecución, permite sobrescribir métodos del sistema sin herencia. Bibliotecas como Aspects y JRSwizzle utilizan esta capacidad para AOP (programación orientada a aspectos) — monitoreo, analítica y registro.
Forward invocation es otra característica del runtime: si un objeto no responde a un selector, el sistema llama a forwardInvocation:, permitiendo reenviar el mensaje a otro objeto. Esta es la base del patrón Proxy en Objective-C (NSProxy), utilizado para inicialización perezosa y objetos distribuidos.
Apple recomienda minimizar el uso de trucos del runtime en código nuevo, prefiriendo el tipado estático de Swift. Sin embargo, en proyectos heredados, el conocimiento de objc_msgSend, method_exchangeImplementations y objc_getAssociatedObject es necesario para mantener la base de código existente.
Objective-C soporta propiedades como azúcar sintáctico sobre ivar con getters/setters. Los modificadores atomic/nonatomic, strong/weak/copy, readonly/readwrite y assign/retain determinan el comportamiento de memoria y la seguridad de hilos. Key-Value Observing (KVO) es un mecanismo para observar cambios en propiedades, integrado en el runtime: cualquier objeto puede suscribirse a cambios en las propiedades de otro objeto mediante addObserver.
Preguntas frecuentes
Una llamada a método se ve como [object selector:argument]. El mensaje pasa a través de objc_msgSend, que encuentra dinámicamente la implementación en el runtime. Un selector es un nombre de método (@selector(methodName)), no un puntero a función. Esto permite swizzling y forward invocation.
Una Categoría (@interface ClassName (Name)) añade métodos a cualquier clase (incluidas las del sistema) sin herencia. Una Extensión (@interface ClassName ()) se declara en un archivo .m y puede añadir propiedades e ivars. Una Categoría no puede añadir ivars, pero una Extensión sí.
Los Bloques son funciones anónimas con sintaxis ^(parámetros) { cuerpo }, que capturan variables del contexto. Son análogos a las lambdas en C++ y a los closures en Swift. Requieren __weak para prevenir retain cycles al capturar self. Se usan en UIKit, GCD y Foundation.
MRC es recuento manual de referencias: el programador llama a retain, release, autorelease. ARC es automático: el compilador inserta retain/release basándose en análisis estático. ARC no es GC — los objetos se liberan inmediatamente cuando el contador llega a cero. ARC soporta los modificadores __weak y __strong.
Sí, mediante un Bridging Header. Swift ve Objective-C a través de este encabezado, Objective-C ve Swift mediante <ProjectName>-Swift.h. Las clases Swift deben heredar de NSObject y marcarse con @objc. Los struct y enum de Swift no son visibles directamente para Objective-C.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también