├── BDLAlertSequenceManager.h ├── BDLAlertSequenceManager.m ├── GCDTimer.h ├── GCDTimer.m ├── README.md ├── SequenceManager.swift ├── SteadilyTrackingOptimizer.h └── SteadilyTrackingOptimizer.m /BDLAlertSequenceManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // BDLAlertSequenceManager.h 3 | // TangTradePlatform 4 | // 5 | // Created by flh-qkl on 2018/9/20. 6 | // Copyright © 2018年 com.tang.trade. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef void(^Transaction)(); 11 | @interface BDLAlertSequenceManager : NSObject 12 | + (instancetype)shareInstance; 13 | - (void)commitTransaction:(Transaction)transaction; 14 | - (void)free; 15 | @end 16 | -------------------------------------------------------------------------------- /BDLAlertSequenceManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // BDLAlertSequenceManager.m 3 | // TangTradePlatform 4 | // 5 | // Created by flh-qkl on 2018/9/20. 6 | // Copyright © 2018年 com.tang.trade. All rights reserved. 7 | // 8 | 9 | #import "BDLAlertSequenceManager.h" 10 | 11 | static BDLAlertSequenceManager *manager = nil; 12 | static BOOL isGenesis = YES; 13 | @interface BDLAlertSequenceManager () 14 | @property (nonatomic)dispatch_semaphore_t sema; 15 | @property (nonatomic)dispatch_queue_t sequenceQueue; 16 | @end 17 | 18 | @implementation BDLAlertSequenceManager 19 | + (instancetype)shareInstance{ 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | if (!manager) { 23 | manager = [BDLAlertSequenceManager new]; 24 | } 25 | }); 26 | return manager; 27 | } 28 | 29 | - (void)commitTransaction:(Transaction)transaction{ 30 | if (transaction) { 31 | dispatch_async(self.sequenceQueue, ^{ 32 | if (!isGenesis) { 33 | dispatch_semaphore_wait(self.sema, DISPATCH_TIME_FOREVER); 34 | } 35 | isGenesis = NO; 36 | dispatch_async(dispatch_get_main_queue(), ^{ 37 | transaction(); 38 | }); 39 | }); 40 | } 41 | } 42 | 43 | - (void)free{ 44 | dispatch_semaphore_signal(self.sema); 45 | } 46 | 47 | #pragma mark - lazy loading 48 | - (dispatch_queue_t)sequenceQueue{ 49 | if (!_sequenceQueue) { 50 | _sequenceQueue = dispatch_queue_create("alert_sq_queue", DISPATCH_QUEUE_SERIAL); 51 | } 52 | return _sequenceQueue; 53 | } 54 | - (dispatch_semaphore_t)sema{ 55 | if (!_sema) { 56 | _sema = dispatch_semaphore_create(0); 57 | } 58 | return _sema; 59 | } 60 | @end 61 | -------------------------------------------------------------------------------- /GCDTimer.h: -------------------------------------------------------------------------------- 1 | // 2 | // GCDTimer.h 3 | // Face_meal 4 | // 5 | // Created by funny on 2017/12/20. 6 | // Copyright © 2017年 fu. All rights reserved. 7 | // GCD计时器封装 8 | 9 | #import 10 | 11 | typedef void (^task)(); 12 | typedef NS_ENUM(NSUInteger,GCDTimerStatues) { 13 | GCDTimerNeedResume, 14 | GCDTimerWorking, 15 | GCDTimerSuspend, 16 | }; 17 | @interface GCDTimer : NSObject 18 | @property (nonatomic, assign)GCDTimerStatues statues; 19 | /** 20 | init 21 | 22 | @param sec 延迟多少s执行 23 | @param padding_sec 间隔多少秒 24 | @param task 要执行的任务 25 | @return instancetype id 26 | */ 27 | - (instancetype)initWithStartAfter:(CGFloat)sec 28 | padding:(CGFloat)padding_sec 29 | task:(task)task; 30 | 31 | /** 32 | 启动或恢复启动 33 | */ 34 | - (void)resume; 35 | 36 | /** 37 | 挂起 38 | */ 39 | - (void)suspend; 40 | - (void)cancle; 41 | @end 42 | -------------------------------------------------------------------------------- /GCDTimer.m: -------------------------------------------------------------------------------- 1 | // 2 | // GCDTimer.m 3 | // Face_meal 4 | // 5 | // Created by funny on 2017/12/20. 6 | // Copyright © 2017年 fu. All rights reserved. 7 | // 8 | 9 | #import "GCDTimer.h" 10 | 11 | @interface GCDTimer () 12 | 13 | /** 14 | 定时器 15 | */ 16 | @property (nonatomic)dispatch_source_t timer; 17 | @end 18 | 19 | @implementation GCDTimer 20 | 21 | /** 22 | init 23 | 24 | @param sec 延迟多久执行,单位为s 25 | @param padding_sec 计时间隔,单位为s 26 | @param task 执行的任务 27 | @return 28 | */ 29 | - (instancetype)initWithStartAfter:(CGFloat)sec 30 | padding:(CGFloat)padding_sec 31 | task:(task)task{ 32 | if (self = [super init]) { 33 | dispatch_queue_t queue = dispatch_get_global_queue(0, 0); 34 | self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 35 | 0, 36 | 0, 37 | queue); 38 | //开始时间 39 | dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, 40 | sec * NSEC_PER_SEC); 41 | //间隔时间 42 | uint64_t interval = padding_sec * NSEC_PER_SEC; 43 | dispatch_source_set_timer(self.timer, 44 | start, 45 | interval, 46 | 0); 47 | //设置回调 48 | if (task) { 49 | dispatch_source_set_event_handler(self.timer, 50 | task); 51 | } 52 | self.statues = GCDTimerNeedResume; 53 | } 54 | return self; 55 | } 56 | 57 | /** 58 | 恢复 59 | */ 60 | - (void)resume{ 61 | if (self.timer && (self.statues == GCDTimerNeedResume ||self.statues == GCDTimerSuspend)) { 62 | dispatch_resume(self.timer); 63 | self.statues = GCDTimerWorking; 64 | } 65 | } 66 | 67 | /** 68 | 挂起 69 | */ 70 | - (void)suspend{ 71 | if (self.timer) { 72 | dispatch_suspend(self.timer); 73 | self.statues = GCDTimerSuspend; 74 | } 75 | } 76 | 77 | - (void)cancle{ 78 | if (self.timer) { 79 | dispatch_cancel(self.timer); 80 | } 81 | } 82 | @end 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # optimizer 2 | iOS开发过程中积累的程序优化工具,包括UI的顺序执行,自定义可挂起和重启的Timer,UI线程的优化以及控制 3 | 4 | ### BDLAlertSequenceManager 5 | 通过信号量和一个异步串行队列管理alert等UI的顺序弹出,用法超级简单,只需要把UI的初始化代码提交到管理类,在UI消失的时候free掉即可。 6 | ### GCDTimer 7 | 使用GCD自定义的Timer,不会受到滑动视图的影响,可以暂停,可以重启,可以取消。 8 | ### SteadilyTrackingOptimizer 9 | 监听了UI线程,可以通过自主控制一些卡顿主线程的任务的执行时机,从而解决一些卡顿问题。 10 | 11 | -------------------------------------------------------------------------------- /SequenceManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SequenceManager.swift 3 | // 4 | 5 | import Foundation 6 | 7 | public class SequenceManager: NSObject { 8 | 9 | public static let share = SequenceManager() 10 | public typealias Transaction = () -> Void 11 | 12 | private var lock = NSLock() 13 | private var isGenesis = true 14 | private var transactionCount = 0 15 | private lazy var sequenceQueue: DispatchQueue = DispatchQueue(label: "sequence_queue") 16 | private lazy var sema: DispatchSemaphore = DispatchSemaphore(value: 0) 17 | 18 | /// 使用时,每个事务必须对应一个free 19 | public func commitTransaction(transaction: @escaping Transaction) { 20 | lock.lock() 21 | transactionCount += 1 22 | lock.unlock() 23 | sequenceQueue.async { 24 | self.lock.lock() 25 | if !self.isGenesis { 26 | self.isGenesis = false 27 | self.lock.unlock() 28 | self.sema.wait() 29 | } 30 | 31 | self.isGenesis = false 32 | if self.transactionCount > 0 { 33 | self.transactionCount -= 1 34 | if self.transactionCount == 0 { 35 | self.isGenesis = true 36 | } 37 | } 38 | self.lock.unlock() 39 | 40 | DispatchQueue.main.async { 41 | transaction() 42 | } 43 | } 44 | } 45 | 46 | public func free() { 47 | guard transactionCount > 0 else { 48 | return 49 | } 50 | sema.signal() 51 | } 52 | 53 | public func reset() { 54 | guard transactionCount > 0 else { 55 | return 56 | } 57 | for _ in 0.. 添加优化器 --> 在滑动试图中,将耗时的UI加载操作丢到addTask方法的block中即可优化完成,尽量减少task中的任务数。 12 | */ 13 | 14 | #import 15 | 16 | typedef void(^taskBlock)(void); 17 | 18 | @interface SteadilyTrackingOptimizer : NSObject 19 | /** 20 | 将任务添加到优化器中 21 | 22 | @param task 要执行的UI任务 23 | @param activity 选择在runloop的什么状态下执行此任务 24 | @param maxQueue 此任务的最大任务数 25 | @param isTrcking 是否是滑动视图的tracking模式 26 | */ 27 | - (void)addTaskInTime:(CFRunLoopActivity)activity 28 | maxQueue:(NSUInteger)maxQueue 29 | isTracking:(BOOL)isTrcking 30 | task:(taskBlock)task; 31 | 32 | /** 33 | 添加优化器,最好在viewWillApper中执行 34 | */ 35 | - (void)addOptimizer; 36 | 37 | /** 38 | 移除优化器,最好在界面消失时执行 39 | */ 40 | - (void)removeOptimizer; 41 | @end 42 | -------------------------------------------------------------------------------- /SteadilyTrackingOptimizer.m: -------------------------------------------------------------------------------- 1 | // 2 | // SteadilyTrackingHelper.m 3 | // Face_meal 4 | // 5 | // Created by 沙少盼 on 2017/11/6. 6 | // Copyright © 2017年 fu. All rights reserved. 7 | // 8 | 9 | #import "SteadilyTrackingOptimizer.h" 10 | 11 | #define DEFULT_MAX_QUEUE_COUNT 100 12 | @interface SteadilyTrackingOptimizer () 13 | { 14 | CFRunLoopRef _runloop; 15 | CFRunLoopObserverRef _runloopO; 16 | } 17 | @property (nonatomic,copy)NSMutableDictionary *tasks; 18 | 19 | //@property (nonatomic,strong)NSTimer *timer; 20 | @end 21 | 22 | @implementation SteadilyTrackingOptimizer 23 | 24 | - (instancetype)init{ 25 | if (self = [super init]) { 26 | // _timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(runloopTimer) userInfo:nil repeats:YES]; 27 | [self initObserver]; 28 | } 29 | return self; 30 | } 31 | //- (void)runloopTimer{} 32 | 33 | - (NSMutableDictionary *)tasks{ 34 | if (!_tasks) { 35 | _tasks = @{}.mutableCopy; 36 | } 37 | return _tasks; 38 | } 39 | 40 | - (void)addTaskInTime:(CFRunLoopActivity)activity 41 | maxQueue:(NSUInteger)maxQueue 42 | isTracking:(BOOL)isTrcking 43 | task:(taskBlock)task{ 44 | 45 | NSMutableArray *tasks = [self.tasks objectForKey:@(activity)]; 46 | if (!tasks) { 47 | tasks = @[].mutableCopy; 48 | } 49 | [tasks addObject:task]; 50 | 51 | if (isTrcking && tasks.count > (maxQueue ? maxQueue : DEFULT_MAX_QUEUE_COUNT)) { 52 | [tasks removeObjectAtIndex:0]; 53 | } 54 | [self.tasks setObject:tasks forKey:@(activity)]; 55 | } 56 | 57 | static void CallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){ 58 | SteadilyTrackingOptimizer *optimizer = (__bridge SteadilyTrackingOptimizer *)info; 59 | NSMutableArray *tasks = [optimizer.tasks objectForKey:@(activity)]; 60 | if (tasks.count == 0) { 61 | return; 62 | } 63 | taskBlock task = tasks.firstObject; 64 | if (task) { 65 | task(); 66 | [tasks removeObject:task]; 67 | [optimizer.tasks setObject:tasks forKey:@(activity)]; 68 | } 69 | } 70 | - (void)initObserver{ 71 | //拿到当前runloop 72 | CFRunLoopRef runloop = CFRunLoopGetCurrent(); 73 | _runloop = runloop; 74 | //定义一个观察者 75 | static CFRunLoopObserverRef defultModeO; 76 | //定义一个上下文 77 | CFRunLoopObserverContext context = { 78 | 0, 79 | (__bridge void *)(self), 80 | &CFRetain, 81 | &CFRelease, 82 | NULL 83 | }; 84 | defultModeO = CFRunLoopObserverCreate(NULL, kCFRunLoopAllActivities, YES, 0, &CallBack, &context); 85 | _runloopO = defultModeO; 86 | } 87 | - (void)addOptimizer{ 88 | //添加观察者 89 | if (!_runloopO || !_runloop) { 90 | [self initObserver]; 91 | } 92 | CFRunLoopAddObserver(_runloop, _runloopO, kCFRunLoopCommonModes); 93 | } 94 | - (void)removeOptimizer{ 95 | //移除观察者 96 | CFRunLoopRemoveObserver(_runloop, _runloopO, kCFRunLoopCommonModes); 97 | } 98 | - (void)dealloc{ 99 | NSLog(@"Optimizer dealloc"); 100 | } 101 | @end 102 | --------------------------------------------------------------------------------