ReactorKitRuntime.m 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #import <objc/runtime.h>
  2. #import "ReactorKitRuntime.h"
  3. @implementation NSObject (ReactorKit)
  4. + (void)load {
  5. static dispatch_once_t onceToken;
  6. dispatch_once(&onceToken, ^{
  7. [self swizzleInitializeOfClassNamed:@"UIViewController"];
  8. [self swizzleInitializeOfClassNamed:@"NSViewController"];
  9. });
  10. }
  11. + (void)swizzleInitializeOfClassNamed:(NSString *)className {
  12. Class class = NSClassFromString(className);
  13. if (!class) {
  14. return;
  15. }
  16. method_exchangeImplementations(class_getClassMethod(class, @selector(initialize)),
  17. class_getClassMethod(self, @selector(_reactorkit_initialize)));
  18. }
  19. + (void)_reactorkit_initialize {
  20. [self _reactorkit_initialize];
  21. BOOL isUIViewController = [self isSubclassOfClassNamed:@"UIViewController"];
  22. BOOL isNSViewController = [self isSubclassOfClassNamed:@"NSViewController"];
  23. if (!isUIViewController && !isNSViewController) {
  24. return;
  25. }
  26. [self swizzleViewDidLoad];
  27. }
  28. + (void)swizzleViewDidLoad {
  29. Class class = self;
  30. #pragma clang diagnostic push
  31. #pragma clang diagnostic ignored "-Wundeclared-selector"
  32. SEL oldSelector = @selector(viewDidLoad);
  33. SEL performBindingSelector = @selector(_reactorkit_performBinding);
  34. #pragma clang diagnostic pop
  35. Method oldMethod = class_getInstanceMethod(class, oldSelector);
  36. const char *types = method_getTypeEncoding(oldMethod);
  37. void (*oldMethodImp)(id, SEL) = (void (*)(id, SEL))method_getImplementation(oldMethod);
  38. IMP newMethodImp = imp_implementationWithBlock(^(__unsafe_unretained id self) {
  39. oldMethodImp(self, oldSelector);
  40. if ([self respondsToSelector:performBindingSelector]) {
  41. #pragma clang diagnostic push
  42. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  43. [self performSelector:performBindingSelector];
  44. #pragma clang diagnostic pop
  45. }
  46. });
  47. class_replaceMethod(class, oldSelector, newMethodImp, types);
  48. }
  49. + (BOOL)isSubclassOfClassNamed:(NSString *)className {
  50. Class superclass = NSClassFromString(className);
  51. if (!superclass) {
  52. return NO;
  53. }
  54. return [self isSubclassOfClass:superclass];
  55. }
  56. @end