// Nombre desde selector
NSString *nombre = NSStringFromSelector(@selector(procesarDato:));
// Punor a implementación
IMP direccion = [self methodForSelector:@selector(procesarDato:)];
}
</div>APIs centrales del runtime
--------------------------
<div>El framework `<objc/runtime.h>` proporciona tres funciones principales para manipular implementaciones:</div><div>| Función | Propósito |
|---|---|
| `method_exchangeImplementations` | Intercambia las IMP de dos métodos de forma atómica |
| `method_setImplementation` | Establece dircetamente la IMP de un método |
| `class_replaceMethod` | Reemplaza o añade un método en una clase |
</div><div>```
// Intercambio atómico equivalente a:
// IMP temp1 = method_getImplementation(mA);
// IMP temp2 = method_getImplementation(mB);
// method_setImplementation(mA, temp2);
// method_setImplementation(mB, temp1);
void method_exchangeImplementations(Method m1, Method m2);
// Reemplazo unidireccional
IMP method_setImplementation(Method m, IMP imp);
@interface ControladorPrincipal ()
- (void)ejecutarIntercambio;
- (int)metodoBase; @end
// Punor donde almacenaremos la implementación original static IMP __implementacion_original;
// Función de reemplazo con firma de método de instancia int funcionSustituta(id instancia, SEL comando) { // Verificación: el selector debe coincidir NSString *nombreActual = NSStringFromSelector(comando); NSAssert([nombreActual isEqualToString:@"metodoBase"], @"Selector inesperado: %@", nombreActual);
NSLog(@"Ejecutando lógica sustituta");
return 42;
}
@implementation ControladorPrincipal
-
(void)ejecutarIntercambio { Method referencia = class_getInstanceMethod([self class], @selector(metodoBase)); __implementacion_original = method_setImplementation(referencia, (IMP)funcionSustituta); }
-
(int)metodoBase { NSLog(@"Implementación original activa"); return 10; }
-
(void)viewDidLoad { [super viewDidLoad];
// Verificación previa al intercambio int valorInicial = [self metodoBase]; NSAssert(valorInicial == 10, @"Resultado base incorrecto");
// Activamos el swizzling [self ejecutarIntercambio];
// Verificación posterior al intercambio int valorModificado = [self metodoBase]; NSAssert(valorModificado == 42, @"Swizzling no aplicado correctamente"); }
@end
</div><div>Es fundamental notar que `method_setImplementation` realiza un **reemplazo unidireccional**: la implementación anterior queda almacenada en el puntero retornado, permitiendo potencialmente restaurar el comportamiento original. Para intercambios bidireccionales donde ambos métodos deben permanecer accesibles, `method_exchangeImplementations` resulta más apropiado al garantizar atomicidad en la operación.</div>