One solution is swizzle out the IMP for the method with super's IMP and call it and then swizzle back.
This is how wax did it.
Code taken from https://github.com/probablycorey/wax/blob/master/lib/wax_instance.m
static int superMethodClosure(lua_State *L) {
wax_instance_userdata *instanceUserdata = (wax_instance_userdata *)luaL_checkudata(L, 1, WAX_INSTANCE_METATABLE_NAME);
const char *selectorName = luaL_checkstring(L, lua_upvalueindex(1));
// If the only arg is 'self' and there is a selector with no args. USE IT!
if (lua_gettop(L) == 1 && lua_isstring(L, lua_upvalueindex(2))) {
selectorName = luaL_checkstring(L, lua_upvalueindex(2));
}
SEL selector = sel_getUid(selectorName);
// Super Swizzle
Method selfMethod = class_getInstanceMethod([instanceUserdata->instance class], selector);
Method superMethod = class_getInstanceMethod(instanceUserdata->isSuper, selector);
if (superMethod && selfMethod != superMethod) { // Super's got what you're looking for
IMP selfMethodImp = method_getImplementation(selfMethod);
IMP superMethodImp = method_getImplementation(superMethod);
method_setImplementation(selfMethod, superMethodImp);
methodClosure(L);
method_setImplementation(selfMethod, selfMethodImp); // Swap back to self's original method
}
else {
methodClosure(L);
}
return 1;
}
As @JesseRusak point out, this is not thread-safe so you need to lock it. Also it may have problem with recursive call.
for objc_msgSendSuper_stret
you can check this answer
objc_super superstruct = {self, [SuperClass class]};
CGSize size = ((CGSize(*)(struct objc_super *, SEL, NSString*))objc_msgSendSuper_stret)(&superstruct , @selector(contentSize:), text);
also for this code
struct objc_super super = {
self,
[self superclass]
};
generally you don't want to use [self superclass]
because it may cause infinite loop. you can try to figure out what happen when subclass is calling super. you need to somehow make sure calling super is not calling this method again.