一种解决方案是用 super 的 IMP 调配方法的 IMP 并调用它,然后调配回来。
就是这样wax https://github.com/probablycorey/wax did it.
代码取自https://github.com/probouslycorey/wax/blob/master/lib/wax_instance.m 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;
}
正如@JesseRusak 指出的,这不是线程安全的,所以你需要锁定它。递归调用也可能有问题。
for objc_msgSendSuper_stret
你可以检查这个answer https://stackoverflow.com/a/8406105/642626
objc_super superstruct = {self, [SuperClass class]};
CGSize size = ((CGSize(*)(struct objc_super *, SEL, NSString*))objc_msgSendSuper_stret)(&superstruct , @selector(contentSize:), text);
也适用于这段代码
struct objc_super super = {
self,
[self superclass]
};
通常你不想使用[self superclass]
因为它可能会导致无限循环。你可以尝试弄清楚当子类调用 super 时会发生什么。您需要以某种方式确保调用 super 不会再次调用此方法。