YYTransaction.m 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //
  2. // YYTransaction.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 15/4/18.
  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 "YYTransaction.h"
  12. @interface YYTransaction()
  13. @property (nonatomic, strong) id target;
  14. @property (nonatomic, assign) SEL selector;
  15. @end
  16. static NSMutableSet *transactionSet = nil;
  17. static void YYRunLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
  18. if (transactionSet.count == 0) return;
  19. NSSet *currentSet = transactionSet;
  20. transactionSet = [NSMutableSet new];
  21. [currentSet enumerateObjectsUsingBlock:^(YYTransaction *transaction, BOOL *stop) {
  22. #pragma clang diagnostic push
  23. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  24. [transaction.target performSelector:transaction.selector];
  25. #pragma clang diagnostic pop
  26. }];
  27. }
  28. static void YYTransactionSetup() {
  29. static dispatch_once_t onceToken;
  30. dispatch_once(&onceToken, ^{
  31. transactionSet = [NSMutableSet new];
  32. CFRunLoopRef runloop = CFRunLoopGetMain();
  33. CFRunLoopObserverRef observer;
  34. observer = CFRunLoopObserverCreate(CFAllocatorGetDefault(),
  35. kCFRunLoopBeforeWaiting | kCFRunLoopExit,
  36. true, // repeat
  37. 0xFFFFFF, // after CATransaction(2000000)
  38. YYRunLoopObserverCallBack, NULL);
  39. CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
  40. CFRelease(observer);
  41. });
  42. }
  43. @implementation YYTransaction
  44. + (YYTransaction *)transactionWithTarget:(id)target selector:(SEL)selector{
  45. if (!target || !selector) return nil;
  46. YYTransaction *t = [YYTransaction new];
  47. t.target = target;
  48. t.selector = selector;
  49. return t;
  50. }
  51. - (void)commit {
  52. if (!_target || !_selector) return;
  53. YYTransactionSetup();
  54. [transactionSet addObject:self];
  55. }
  56. - (NSUInteger)hash {
  57. long v1 = (long)((void *)_selector);
  58. long v2 = (long)_target;
  59. return v1 ^ v2;
  60. }
  61. - (BOOL)isEqual:(id)object {
  62. if (self == object) return YES;
  63. if (![object isMemberOfClass:self.class]) return NO;
  64. YYTransaction *other = object;
  65. return other.selector == _selector && other.target == _target;
  66. }
  67. @end