New file |
| | |
| | | // |
| | | // YYTransaction.m |
| | | // YYKit <https://github.com/ibireme/YYKit> |
| | | // |
| | | // Created by ibireme on 15/4/18. |
| | | // Copyright (c) 2015 ibireme. |
| | | // |
| | | // This source code is licensed under the MIT-style license found in the |
| | | // LICENSE file in the root directory of this source tree. |
| | | // |
| | | |
| | | #import "YYTransaction.h" |
| | | |
| | | |
| | | @interface YYTransaction() |
| | | @property (nonatomic, strong) id target; |
| | | @property (nonatomic, assign) SEL selector; |
| | | @end |
| | | |
| | | static NSMutableSet *transactionSet = nil; |
| | | |
| | | static void YYRunLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) { |
| | | if (transactionSet.count == 0) return; |
| | | NSSet *currentSet = transactionSet; |
| | | transactionSet = [NSMutableSet new]; |
| | | [currentSet enumerateObjectsUsingBlock:^(YYTransaction *transaction, BOOL *stop) { |
| | | #pragma clang diagnostic push |
| | | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" |
| | | [transaction.target performSelector:transaction.selector]; |
| | | #pragma clang diagnostic pop |
| | | }]; |
| | | } |
| | | |
| | | static void YYTransactionSetup() { |
| | | static dispatch_once_t onceToken; |
| | | dispatch_once(&onceToken, ^{ |
| | | transactionSet = [NSMutableSet new]; |
| | | CFRunLoopRef runloop = CFRunLoopGetMain(); |
| | | CFRunLoopObserverRef observer; |
| | | |
| | | observer = CFRunLoopObserverCreate(CFAllocatorGetDefault(), |
| | | kCFRunLoopBeforeWaiting | kCFRunLoopExit, |
| | | true, // repeat |
| | | 0xFFFFFF, // after CATransaction(2000000) |
| | | YYRunLoopObserverCallBack, NULL); |
| | | CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes); |
| | | CFRelease(observer); |
| | | }); |
| | | } |
| | | |
| | | |
| | | @implementation YYTransaction |
| | | |
| | | + (YYTransaction *)transactionWithTarget:(id)target selector:(SEL)selector{ |
| | | if (!target || !selector) return nil; |
| | | YYTransaction *t = [YYTransaction new]; |
| | | t.target = target; |
| | | t.selector = selector; |
| | | return t; |
| | | } |
| | | |
| | | - (void)commit { |
| | | if (!_target || !_selector) return; |
| | | YYTransactionSetup(); |
| | | [transactionSet addObject:self]; |
| | | } |
| | | |
| | | - (NSUInteger)hash { |
| | | long v1 = (long)((void *)_selector); |
| | | long v2 = (long)_target; |
| | | return v1 ^ v2; |
| | | } |
| | | |
| | | - (BOOL)isEqual:(id)object { |
| | | if (self == object) return YES; |
| | | if (![object isMemberOfClass:self.class]) return NO; |
| | | YYTransaction *other = object; |
| | | return other.selector == _selector && other.target == _target; |
| | | } |
| | | |
| | | @end |