NSObject+SXRuntime.m 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. //
  2. // NSObject+SXRuntime.m
  3. // UINavigation-SXFixSpace
  4. //
  5. // Created by charles on 2017/9/8.
  6. // Copyright © 2017年 None. All rights reserved.
  7. //
  8. #import "NSObject+SXRuntime.h"
  9. char * const kProtectCrashProtectorName = "kProtectCrashProtector";
  10. void ProtectCrashProtected(id self, SEL sel) {
  11. }
  12. @implementation NSObject (SXRuntime)
  13. // MARK: Util
  14. + (void)swizzleClassMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel {
  15. Class cls = object_getClass(self);
  16. Method originAddObserverMethod = class_getClassMethod(cls, oriSel);
  17. Method swizzledAddObserverMethod = class_getClassMethod(cls, swiSel);
  18. [self swizzleMethodWithOriginSel:oriSel oriMethod:originAddObserverMethod swizzledSel:swiSel swizzledMethod:swizzledAddObserverMethod class:cls];
  19. }
  20. + (void)swizzleInstanceMethodWithOriginSel:(SEL)oriSel swizzledSel:(SEL)swiSel {
  21. Method originAddObserverMethod = class_getInstanceMethod(self, oriSel);
  22. Method swizzledAddObserverMethod = class_getInstanceMethod(self, swiSel);
  23. [self swizzleMethodWithOriginSel:oriSel oriMethod:originAddObserverMethod swizzledSel:swiSel swizzledMethod:swizzledAddObserverMethod class:self];
  24. }
  25. + (void)swizzleMethodWithOriginSel:(SEL)oriSel
  26. oriMethod:(Method)oriMethod
  27. swizzledSel:(SEL)swizzledSel
  28. swizzledMethod:(Method)swizzledMethod
  29. class:(Class)cls {
  30. BOOL didAddMethod = class_addMethod(cls, oriSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
  31. if (didAddMethod) {
  32. class_replaceMethod(cls, swizzledSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
  33. } else {
  34. method_exchangeImplementations(oriMethod, swizzledMethod);
  35. }
  36. }
  37. + (Class)addMethodToStubClass:(SEL)aSelector {
  38. Class ProtectCrashProtector = objc_getClass(kProtectCrashProtectorName);
  39. if (!ProtectCrashProtector) {
  40. ProtectCrashProtector = objc_allocateClassPair([NSObject class], kProtectCrashProtectorName, sizeof([NSObject class]));
  41. objc_registerClassPair(ProtectCrashProtector);
  42. }
  43. class_addMethod(ProtectCrashProtector, aSelector, (IMP)ProtectCrashProtected, "v@:");
  44. return ProtectCrashProtector;
  45. }
  46. - (BOOL)isMethodOverride:(Class)cls selector:(SEL)sel {
  47. IMP clsIMP = class_getMethodImplementation(cls, sel);
  48. IMP superClsIMP = class_getMethodImplementation([cls superclass], sel);
  49. return clsIMP != superClsIMP;
  50. }
  51. + (BOOL)isMainBundleClass:(Class)cls {
  52. return cls && [[NSBundle bundleForClass:cls] isEqual:[NSBundle mainBundle]];
  53. }
  54. @end;