IMP class_swizzleSelector(Class clazz, SEL selector, IMP newImplementation) { // If the method does not exist for this class, do nothing Method method = class_getInstanceMethod(clazz, selector); if (! method) { returnNULL; } // Make sure the class implements the method. If this is not the case, inject an implementation, calling 'super' constchar *types = method_getTypeEncoding(method); class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretainedidself, va_list argp) { struct objc_super super = { .receiver = self, .super_class = class_getSuperclass(clazz) }; id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper; return objc_msgSendSuper_typed(&super, selector, argp); }), types); // Can now safely swizzle return class_replaceMethod(clazz, selector, newImplementation, types); }
IMP class_swizzleSelector_stret(Class clazz, SEL selector, IMP newImplementation) { // If the method does not exist for this class, do nothing Method method = class_getInstanceMethod(clazz, selector); if (! method) { returnNULL; } // Make sure the class implements the method. If this is not the case, inject an implementation, only calling 'super' constchar *types = method_getTypeEncoding(method); class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretainedidself, va_list argp) { struct objc_super super = { .receiver = self, .super_class = class_getSuperclass(clazz) }; // Sufficiently large struct typedefstruct LargeStruct_ { char dummy[16]; } LargeStruct; // Cast the call to objc_msgSendSuper_stret appropriately LargeStruct (*objc_msgSendSuper_stret_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper_stret; return objc_msgSendSuper_stret_typed(&super, selector, argp); }), types); // Can now safely swizzle return class_replaceMethod(clazz, selector, newImplementation, types); }