UIGestureRecognizer+LookinServer.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //
  2. // UIGestureRecognizer+LookinServer.m
  3. // LookinServer
  4. //
  5. // Created by Li Kai on 2019/8/14.
  6. // https://lookin.work
  7. //
  8. #import "UIGestureRecognizer+LookinServer.h"
  9. #import <objc/runtime.h>
  10. #import "NSObject+Lookin.h"
  11. #import "LookinTuple.h"
  12. #import "LookinWeakContainer.h"
  13. #import "LookinServerDefines.h"
  14. @implementation UIGestureRecognizer (LookinServer)
  15. #pragma mark - Hook
  16. + (void)load {
  17. static dispatch_once_t onceToken;
  18. dispatch_once(&onceToken, ^{
  19. Method oriMethod = class_getInstanceMethod([self class], @selector(initWithTarget:action:));
  20. Method newMethod = class_getInstanceMethod([self class], @selector(lks_initWithTarget:action:));
  21. method_exchangeImplementations(oriMethod, newMethod);
  22. oriMethod = class_getInstanceMethod([self class], @selector(addTarget:action:));
  23. newMethod = class_getInstanceMethod([self class], @selector(lks_addTarget:action:));
  24. method_exchangeImplementations(oriMethod, newMethod);
  25. oriMethod = class_getInstanceMethod([self class], @selector(removeTarget:action:));
  26. newMethod = class_getInstanceMethod([self class], @selector(lks_removeTarget:action:));
  27. method_exchangeImplementations(oriMethod, newMethod);
  28. });
  29. }
  30. - (instancetype)lks_initWithTarget:(nullable id)target action:(nullable SEL)action {
  31. UIGestureRecognizer *instance = [self lks_initWithTarget:target action:action];
  32. [instance lks_didAddTarget:target action:NSStringFromSelector(action)];
  33. return instance;
  34. }
  35. - (void)lks_addTarget:(id)target action:(SEL)action {
  36. [self lks_addTarget:target action:action];
  37. [self lks_didAddTarget:target action:NSStringFromSelector(action)];
  38. }
  39. - (void)lks_removeTarget:(id)target action:(SEL)action {
  40. [self lks_removeTarget:target action:action];
  41. [self lks_didRemoveTarget:target action:NSStringFromSelector(action)];
  42. }
  43. #pragma mark - Main
  44. - (void)lks_didAddTarget:(id)target action:(NSString *)action {
  45. if (!target || !action.length) {
  46. return;
  47. }
  48. BOOL alreadyExist = [self.lks_targetActions lookin_any:^BOOL(LookinTwoTuple *obj) {
  49. id existTarget = ((LookinWeakContainer *)obj.first).object;
  50. NSString *existAction = (NSString *)obj.second;
  51. if (target == existTarget && [action isEqualToString:existAction]) {
  52. return YES;
  53. }
  54. return NO;
  55. }];
  56. if (alreadyExist) {
  57. return;
  58. }
  59. LookinTwoTuple *newTuple = [LookinTwoTuple new];
  60. newTuple.first = [LookinWeakContainer containerWithObject:target];
  61. newTuple.second = action;
  62. if (!self.lks_targetActions) {
  63. self.lks_targetActions = [NSMutableArray array];
  64. }
  65. [self.lks_targetActions addObject:newTuple];
  66. }
  67. - (void)lks_didRemoveTarget:(id)target action:(NSString *)action {
  68. if (target == nil && action == nil) {
  69. // target 为 nil,action 为 nil 时,表示移除所有 target 的所有已注册监听方法
  70. [self.lks_targetActions removeAllObjects];
  71. return;
  72. }
  73. if (target == nil) {
  74. // target 为 nil,action 为 handleTap 时,表示移除所有 target 的名为 handleTap 的监听方法
  75. [self.lks_targetActions lookin_removeObjectsPassingTest:^BOOL(NSUInteger idx, LookinTwoTuple *obj) {
  76. NSString *currentAction = (NSString *)obj.second;
  77. if ([currentAction isEqualToString:action]) {
  78. return YES;
  79. }
  80. return NO;
  81. }];
  82. return;
  83. }
  84. if (action == nil) {
  85. // target 为 abc,action 为 nil 时,表示移除 abc 的所有已注册监听方法
  86. [self.lks_targetActions lookin_removeObjectsPassingTest:^BOOL(NSUInteger idx, LookinTwoTuple *obj) {
  87. id currentTarget = ((LookinWeakContainer *)obj.first).object;
  88. if (currentTarget == target) {
  89. return YES;
  90. }
  91. return NO;
  92. }];
  93. return;
  94. }
  95. [self.lks_targetActions lookin_removeObjectsPassingTest:^BOOL(NSUInteger idx, LookinTwoTuple *obj) {
  96. id currentTarget = ((LookinWeakContainer *)obj.first).object;
  97. NSString *currentAction = (NSString *)obj.second;
  98. if (currentTarget == target && [currentAction isEqualToString:action]) {
  99. return YES;
  100. }
  101. return NO;
  102. }];
  103. }
  104. - (void)setLks_targetActions:(NSMutableArray<LookinTwoTuple *> *)lks_targetActions {
  105. [self lookin_bindObject:lks_targetActions forKey:@"lks_targetActions"];
  106. }
  107. - (NSMutableArray *)lks_targetActions {
  108. return [self lookin_getBindObjectForKey:@"lks_targetActions"];
  109. }
  110. @end