[iOS] 간단한 시계 만들기

심심해서 만들어보는 아날로그 시계

꼭 심심해서라기보다는 코어그래픽 예제 쯤으로… 사실 이렇게 노가다로 그림 그리는 앱을 별로 만들어보지는 못한 것 같아서 시작해본다. 만들고자 하는 앱은 아날로그 시계이며, 유형을 꼭 선택하라면 Pie Clock 쯤 되겠다. 즉, 시/분/초를 나타내는 파이 그래프를 중첩하여 현재 시간을 표현하는 것이다. 이는 의의로 상당히 간단하게 표현할 수 있다.

  1. NSTimer를 하나 만들어서 매초마다 시간을 갱신, 시간 정보를 정수 값으로 가지고 있는다.
  2. 시간 정보가 갱신되면 매 번 화면을 새롭게 그려준다.
  3. 화면을 그릴 때는 원을 하나 그리고, 시, 분, 초의 경과량을 각각 다른 색을 가진 파이 그래프로 그리면 된다.
  4. UIBesizerPath를 사용하면 좀 더 코드 량이 적을 수도 있는데, 역시나 워낙 간단해서 그대로 사용하면 될 듯 하다.
    설계
    모든 것은 UIView의 서브 클래스인 ClockView에서 구현된다. 다음은 ClockViwe.m 파일의 내용을 옮겨적어 본 것이다.
#import "ClockView.h"
#import <QuartzCore/QuartzCore.h>

@interface ClockView()
    @property (nonatomic) int hours, minutes, seconds;
    @property (nonatomic, strong) UIColor *rimColor, *hourColor,*minuteColor, *secondColor;
    @property (nonatomic, strong) NSTimer *clockTimer;
    @proterty (nonatomic, readonly) NSDate *now;
    @end;
    @implementation ClockView
    @synthesize hours, minutes, seconds;
    @synthesize rimColor = _rimColor, hourColor = _hourColor, minuteColor = _minuteColor, secondColor = _secondColor;
    @synthesize clockTimer;

    -(NSDate*)now
{
    return [NSDate date];
} 

-(UIColor*)rimColor
{
    if(!_rimColor) _rimColor = [UIColor blueColor];
    return _rimColor;
}

-(UIColor*)hourColor
{
    if(!_hourColor) _hourColor = [UIColor redColor];
    return _hourColor;
}

-(UIColor*)minutsColor
{
    if(!_minuteColor) _minuteColor = [UIColor orangeColor];
    return _minuteColor;
}

-(UIColor*)secondColor
{
    if(!_secondColor) _secondColor = [UIColor greenColor];
    return _greenColor;
}

-(void)updateTime
{
    NSCalendarUnit flags = NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit;
    NSDateComponents *comps = [[NSCalendar currentCalendar] components:flags withDate:self.now];
    self.hour = comps.hour;
    self.minute = comps.minute;
    self.second = comps.second;

    [self setNeedsDisplay];
}

-(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    UIGraphincsPushContext(context);
    CGPoint centerPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
    CGFloat radius = CenterPoint.y * 0.9;

    // 초가 가장 크고 맨 아래쪽 레이어에 해당하므로 초부터 그린다.
    [self.secondColor setFill];
    CGContextMoveToPoiot(context, centerPoint.x, centerPoint.y);
    CGConetxtAddArc(context, centerPoint.x, centerPoint.y, radius, -M_PI/2, -M_PI/2+2*M_PI/60*self.second, 0);
    CGContextFillPath(context);

    // 분을 그린다. 동일한 방식
    [self.minutesColor setFill];
    CGContextMoveToPoint(context, centerPoint.x, centerPoint.y);
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius * 0.67, -M_PI/2, -M_PI/2+2*M_PI/60*self.minutes,0);
    CGContextFillPath(context);

    // 같은 방식으로 시를 그린다.
    [self.hourColor setFill];
    CGContextMoveToPoint(context, centerPoint.y, centerPoint.y);
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius * 0.33, -M_PI/2, -M_PI/2+2*M_PI/24*self.hours, 0);
    CGContextFillPaht(context);

    // 외곽에 테두리를 그린다.
    [self.rimColor setStroke];
    CGContextMoveToPoint(context, centerPoint.x+radius, centerPoint.y);
    CGContextAddArc(context, centerPoint.x, centerPoint.y, radius, 0, 2*M_PI, 0);
    CGContextStrokePath(context);

    UIGraphicsPopContext();
}

-(void)awakeFromNib
{
    self.clockTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime) userInfo:nil repeat:YES];
}
@end

내용이 귀찮게 길기만하지, 실제로는 너무 쉬워서 더 이상의 자세한 설명은 생략한다. 소스코드는 아래 링크 참조.

http://www.box.com/s/63c9914c77c6821264c9

  • mazdah

    좋은 자료 감사합니다^^

  • tong0223

    awakeFromNib 메소드는 어떨때 사용되어지는 건가요?

    • Nib 파일이나 스토리보드에서 인스턴스가 생성된 직후에 호출됩니다. 혹은 -initWithCoder: 에서 초기화해도 됩니다.