昨天做一个时钟小demo,发现了一些问题.
描述能力有限,我封装好了一个时钟框架,朋友们可以参考 https://github.com/qianlishun/ClockView
点击这里可以直接下载 Download ZIP
有两种定时器可以用于实现,
在这里我最开始使用了NSTimer
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTimer) userInfo:nil repeats:YES];
使用过程中发现会有误差,即读取本地系统时间时这一秒的0.99秒读到定义的表盘上也会是0秒.不过也可以把 scheduledTimerWithTimeInterval 设定的很小来解决.
最后使用了CADisplayLink
// link默认是1/60 秒执行一次 CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateTimer)]; //执行定时器 把定时器放在主运行循环中执行 [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
获取系统时间
// 实例化日历对象 NSCalendar *calendar = [NSCalendar currentCalendar]; // 获取当前时间的秒数 NSDateComponents *comps = [calendar components:NSCalendarUnitSecond fromDate:[NSDate date]]; // 获取当前时间的分钟数 NSDateComponents *minute = [calendar components:NSCalendarUnitMinute fromDate:[NSDate date]]; // 获取当前时间的小时数 NSDateComponents *hour = [calendar components:NSCalendarUnitHour fromDate:[NSDate date]];
根据系统时间设置时钟指针旋转
//秒针 CGFloat angle = degree2angle(comps.second * 360/60); secHand.affineTransform = CGAffineTransformMakeRotation(angle); // 分针 CGFloat angleM = degree2angle(minute.minute * 360/60); minHand.affineTransform = CGAffineTransformMakeRotation(angleM); // 时针 CGFloat angleH = degree2angle(hour.hour * 30 + minute.minute/10.0 * 5); hourHand.affineTransform = CGAffineTransformMakeRotation(angleH);
最后,秒针的旋转样式是一秒一跳,于是想做一个扫秒式的旋转.
这种秒针旋转样式是一秒一跳
写在 定时器的监听方法updateTimer里
#define degree2angle(angle) ((angle) * M_PI / 180) CGFloat angle = degree2angle(comps.second * 360/60); secHand.affineTransform = CGAffineTransformMakeRotation(angle);
如果想设置为扫秒,则使用CGAffineTransformRotate,每次刷新都走很小的一个角度,这样看起来就是连续的扫秒
secHand.affineTransform = CGAffineTransformRotate(secHand.affineTransform, M_PI *2 /3600);
这里因为没有使用根据当前系统的秒数来控制旋转, 所以需要在初始化表盘时将秒针位置也初始化为系统时间
// 初始化秒针 - (void)secHandRoll{ // 实例化日历对象 NSCalendar *calendar = [NSCalendar currentCalendar]; // 获取当前时间的秒数 NSDateComponents *comps = [calendar components:NSCalendarUnitSecond fromDate:[NSDate date]]; CGFloat angle = degree2angle(comps.second * 360/60); //初始化秒针位置 secHand.affineTransform = CGAffineTransformMakeRotation(angle); }