UIControl+YYAdd.m 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //
  2. // UIControl+YYAdd.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 13/4/5.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "UIControl+YYAdd.h"
  12. #import "YYKitMacro.h"
  13. #import <objc/runtime.h>
  14. YYSYNTH_DUMMY_CLASS(UIControl_YYAdd)
  15. static const int block_key;
  16. @interface _YYUIControlBlockTarget : NSObject
  17. @property (nonatomic, copy) void (^block)(id sender);
  18. @property (nonatomic, assign) UIControlEvents events;
  19. - (id)initWithBlock:(void (^)(id sender))block events:(UIControlEvents)events;
  20. - (void)invoke:(id)sender;
  21. @end
  22. @implementation _YYUIControlBlockTarget
  23. - (id)initWithBlock:(void (^)(id sender))block events:(UIControlEvents)events {
  24. self = [super init];
  25. if (self) {
  26. _block = [block copy];
  27. _events = events;
  28. }
  29. return self;
  30. }
  31. - (void)invoke:(id)sender {
  32. if (_block) _block(sender);
  33. }
  34. @end
  35. @implementation UIControl (YYAdd)
  36. - (void)removeAllTargets {
  37. [[self allTargets] enumerateObjectsUsingBlock: ^(id object, BOOL *stop) {
  38. [self removeTarget:object action:NULL forControlEvents:UIControlEventAllEvents];
  39. }];
  40. [[self _yy_allUIControlBlockTargets] removeAllObjects];
  41. }
  42. - (void)setTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents {
  43. if (!target || !action || !controlEvents) return;
  44. NSSet *targets = [self allTargets];
  45. for (id currentTarget in targets) {
  46. NSArray *actions = [self actionsForTarget:currentTarget forControlEvent:controlEvents];
  47. for (NSString *currentAction in actions) {
  48. [self removeTarget:currentTarget action:NSSelectorFromString(currentAction)
  49. forControlEvents:controlEvents];
  50. }
  51. }
  52. [self addTarget:target action:action forControlEvents:controlEvents];
  53. }
  54. - (void)addBlockForControlEvents:(UIControlEvents)controlEvents
  55. block:(void (^)(id sender))block {
  56. if (!controlEvents) return;
  57. _YYUIControlBlockTarget *target = [[_YYUIControlBlockTarget alloc]
  58. initWithBlock:block events:controlEvents];
  59. [self addTarget:target action:@selector(invoke:) forControlEvents:controlEvents];
  60. NSMutableArray *targets = [self _yy_allUIControlBlockTargets];
  61. [targets addObject:target];
  62. }
  63. - (void)setBlockForControlEvents:(UIControlEvents)controlEvents
  64. block:(void (^)(id sender))block {
  65. [self removeAllBlocksForControlEvents:UIControlEventAllEvents];
  66. [self addBlockForControlEvents:controlEvents block:block];
  67. }
  68. - (void)removeAllBlocksForControlEvents:(UIControlEvents)controlEvents {
  69. if (!controlEvents) return;
  70. NSMutableArray *targets = [self _yy_allUIControlBlockTargets];
  71. NSMutableArray *removes = [NSMutableArray array];
  72. for (_YYUIControlBlockTarget *target in targets) {
  73. if (target.events & controlEvents) {
  74. UIControlEvents newEvent = target.events & (~controlEvents);
  75. if (newEvent) {
  76. [self removeTarget:target action:@selector(invoke:) forControlEvents:target.events];
  77. target.events = newEvent;
  78. [self addTarget:target action:@selector(invoke:) forControlEvents:target.events];
  79. } else {
  80. [self removeTarget:target action:@selector(invoke:) forControlEvents:target.events];
  81. [removes addObject:target];
  82. }
  83. }
  84. }
  85. [targets removeObjectsInArray:removes];
  86. }
  87. - (NSMutableArray *)_yy_allUIControlBlockTargets {
  88. NSMutableArray *targets = objc_getAssociatedObject(self, &block_key);
  89. if (!targets) {
  90. targets = [NSMutableArray array];
  91. objc_setAssociatedObject(self, &block_key, targets, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  92. }
  93. return targets;
  94. }
  95. @end