ReactorKitRuntime.m 2.1 KB

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