preface

I haven’t updated my article for a long time. It’s the first time I posted an article in Digg, but I still set a flag for myself to update at least one article every week. Maybe the quality of the article is not quite satisfactory, so I hope to improve my writing style by writing articles and record the solutions to the problems I have encountered in learning. In the process of learning iOS, I want to make sure that everyone is familiar with timers. In daily development, there will always be functions that need timers. Common timers are NSTimer, GCD and CADisplayLink. There are many tutorials on the Internet to explain the difference between the three. Today’s main topic is GCD use and packaging.

Three general differences

advantages disadvantages
NSTimer Using a simple The timing is not accurate because of Runloop
CADisplayLink High precision The CPU load will affect the triggering event, and the triggering event will cause frame drop if the triggering event is longer than the triggering interval.
GCD More accurate More code, basically not affected by other

Summary: NSTimer and CADisplayLink are susceptible, while GCD has a lot of code but 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); Dispatch_source_t timer = dispatch_source_create(dispatch_source_timer, 0, 0, queue); /** Set timer, here every 10 milliseconds */ dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), 10*NSEC_PER_MSEC, 0); /** Dispatch_source_set_event_handler (timer, ^{//do you want....
});
Copy the code
Start or continue the suspended timer
dispatch_resume(timer);
Copy the code
Pause timer
Dispatch_suspend (dispatch_resume) * suspend (dispatch_resume) * suspend (dispatch_resume) * suspend (dispatch_resume) * suspend (dispatch_resume) * */ dispatch_suspend(timer);Copy the code
End timer
dispatch_source_cancel(timer);
Copy the code

Conception of encapsulation

Before writing the code, conceive the functional modules and the solutions to the problems encountered, the code logic, and then write the code by hand, there will be twice the result with half the effort.
  • Must include start, pause, continue, stop, reset functions
  • Due to loss of accuracy in floating-point calculation, NSDecimal should be used in the calculation process
  • Time conversion considering accuracy and convenience, the system time conversion method is adopted, and the time zone is set to GMT
  • As the APP enters the background, if the switch of background task is not turned on, the timer will stop, and it 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 status of the APP, and whether to continue or end the timer and call back compared with the deadline.
  • The result returned by the timer would have to be processed as a string, so a time class is used to return the result, which can be customized
  • The countdown results return and end notification are in closure form

Part of the code

*/ - (void)appDidEnterBackground{[selfsuspend];
    NSDate *date = [[NSDate alloc] init];
    NSDateFormatter *format = [[NSDateFormatter alloc] init];
    format.dateFormat = @"yyyy-MM-dd HH:mm:ss:SSS"; self.appDidEnterBackgroundTime = [date timeIntervalSince1970]; } - (void)appDidEnterForeground{NSDate *date = [[NSDate alloc] init]; NSDateFormatter *format = [[NSDateFormatter alloc] init]; format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    self.appDidEnterForegroundTime = [date timeIntervalSince1970];
    [self reCalculateMinder];
}
Copy the code
/** / - (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;
}
Copy the code
@property (nonatomic, strong) OMTimer *timer;
Copy the code
self.timer = [[OMTimer alloc] init];
self.timer.timerInterval = 30;
self.timer.precision = 100;
self.timer.isAscend = NO;
self.timer.progressBlock = ^(OMTime *progress) {
     NSLog(@"% @ : % @ : % @ : % @", progress.hour, progress.minute, progress.second, progress.millisecond; }; self.timer.completion = ^{ NSLog(@"complete done!");
};
Copy the code

Swift version

I like OC recently. If you need the Swift version, you can leave a message or write a Swift version, 😜.

conclusion

Use simple, just need to drag omtimer. h and omtimer. m into your project can meet the large number of scenarios, can also increase the countdown time, all code has been on Github

< p style = “padding-bottom: 0px; padding-bottom: 0px; / If you have any questions, please leave a message or send me an email at [email protected]