Preface
I haven't updated the article for a long time. When the Nuggets posted the article for the first time, I still set up a flag for myself to update at least one article a week. The quality of the article may not be very satisfactory. I hope to improve my writing style by writing articles and record the solutions to problems encountered in my studies.
In the process of learning iOS, everyone is familiar with timers. In daily development, they will always encounter functions that require timers. Common timers include NSTimer, GCD, and CADisplayLink. There are also many tutorials online to introduce the differences between the three. Today we mainly talk about the use and packaging of GCD.
The difference between the three
advantage | shortcoming | |
---|---|---|
NSTimer | Easy to use | The impact of Runloop will cause inaccurate timing |
CADisplayLink | High accuracy | When the CPU is loaded, the trigger event will be affected, and the trigger event is greater than the trigger interval, which will cause frame drop. |
GCD | More accurate | There are many codes, basically no other influence |
Summary: NSTimer and CADisplayLink are easily affected, while GCD has a lot of code, but it is very controllable.
GCD
/** Get a global thread to run the timer*/ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); /** Create a timer*/ dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); /** Set the timer, here is executed every 10 milliseconds*/ dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), 10*NSEC_PER_MSEC, 0); /** Set the timer's operation event*/ dispatch_source_set_event_handler(timer, ^{ //do you want.... });
Turn on and continue the paused timer
dispatch_resume(timer);
Pause timer
/** When suspending, pay attention to the fact that multiple pauses will lead to thread locking, that is, how many pauses will be done. * The corresponding number of continuous operations, namely dispatch_suspend and dispatch_resume * Only when the timer continues to work is present in pairs. */ dispatch_suspend(timer);
End timer
dispatch_source_cancel(timer);
Conceive packaging
Before writing code, you should think about the functional modules, solutions to problems you will encounter, and code logic, and then start writing code manually, which will result twice the result with half the effort.
- It must include start, pause, continue, stop, and reset functions
- During the time calculation process, accuracy will be lost due to floating point calculations. The calculation process should use NSDecimal.
- Time conversion takes into account accuracy and convenience, and adopts the system's time conversion method, and the time zone is set to GMT.
- Since the APP enters the background, if the switch of the background task is not turned on, the timer will stop, and the APP will continue again when entering the APP again. Therefore, the time stamp of the APP entering the background and the foreground is recorded by monitoring the app status, and compared with the deadline, whether to continue to count or end the timing and callback.
- If the result returned by the timer is a string, it still needs to be processed. Therefore, a time class is used to return the result, and custom operations can be performed.
- The return and end notification of the countdown result are in closure form
Part of the code
/** app enters the background*/ - (void)appDidEnterBackground{ [self suspend]; NSDate *date = [[NSDate alloc] init]; NSDateFormatter *format = [[NSDateFormatter alloc] init]; = @"yyyy-MM-dd HH:mm:ss:SSS"; = [date timeIntervalSince1970]; } /** app enters the front desk*/ - (void)appDidEnterForeground{ NSDate *date = [[NSDate alloc] init]; NSDateFormatter *format = [[NSDateFormatter alloc] init]; = @"yyyy-MM-dd HH:mm:ss"; = [date timeIntervalSince1970]; [self reCalculateMinder]; } /** Unabsorbed accuracy calculation results*/ - (NSDecimalNumber *)value: (NSTimeInterval)value byOpration: (OMDecimalOprationType)byOpration percision: (NSInteger)percision withValue: (NSTimeInterval)withValue{ NSDecimalNumber *number = [self numberValueWithString: value]; NSDecimalNumber *withNumber = [self numberValueWithString: withValue]; NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode: NSRoundPlain scale: percision raiseOnExactness: NO raiseOnOverflow: NO raiseOnUnderflow: NO raiseOnDivideByZero: YES]; switch (byOpration) { case OMDecimalOprationTypeAdd: return [number decimalNumberByAdding: withNumber withBehavior:handler]; break; case OMDecimalOprationTypeSubtract: return [number decimalNumberBySubtracting: withNumber withBehavior: handler]; break; case OMDecimalOprationTypeDivide: return [number decimalNumberByDividingBy: withNumber withBehavior: handler]; break; case OMDecimalOprationTypeMultiple: return [number decimalNumberByMultiplyingBy: withNumber withBehavior: handler]; break; default: break; return nil; }
@property (nonatomic, strong) OMTimer *timer;
= [[OMTimer alloc] init]; = 30; = 100; = NO; = ^(OMTime *progress) { NSLog(@"%@:%@:%@:%@", , , , ; }; = ^{ NSLog(@"complete done!"); };
Swift version
I have fallen in love with OC recently. If you need a Swift version, you can leave a message or private me. You can write a Swift version:stuck_out_tongue_winking_eye:.
Conclusion
Simple to use, just drag the sum into your project, satisfying the scenario of large numbers, counting down or increasing the timing, all codes are already on Github</oymuzi/OMKit/
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.