Skip to content

Instantly share code, notes, and snippets.

@storoj
Created December 1, 2020 12:55
Show Gist options
  • Save storoj/edd0a664eab6a2f59754795e027a0e35 to your computer and use it in GitHub Desktop.
Save storoj/edd0a664eab6a2f59754795e027a0e35 to your computer and use it in GitHub Desktop.
ObjC Hachik
#import <objc/runtime.h>
#import <objc/message.h>
template <typename RET, typename ...Types>
class ObjcMethodHook {
typedef RET(*_IMP)(id _self, SEL _cmd, Types...);
typedef RET(^_IMPBlock)(id _self, Types...);
private:
Class m_cls;
SEL m_sel;
_IMP m_orig;
public:
ObjcMethodHook(Class cls, SEL sel) : m_cls(cls), m_sel(sel), m_orig(NULL) {};
ObjcMethodHook(const char *cls, const char *sel) : ObjcMethodHook(objc_lookUpClass(cls), sel_getUid(sel)) {};
void hook(_IMPBlock imp) {
Method m = class_getInstanceMethod(m_cls, m_sel);
m = class_getInstanceMethod(m_cls, m_sel);
m_orig = (_IMP)class_replaceMethod(m_cls, m_sel, imp_implementationWithBlock(imp), method_getTypeEncoding(m));
};
RET super(id _self, Types... args) {
if (m_orig) {
return m_orig(_self, m_sel, args...);
} else {
struct objc_super s = {
_self,
class_getSuperclass(m_cls)
};
return ((_IMP)objc_msgSendSuper)((__bridge id)&s, m_sel, args...);
}
};
RET call(id _self, Types... args) {
return ((_IMP)objc_msgSend)(_self, m_sel, args...);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment