이번에는 저번 바이오리듬 보다 조금 기능을 추가하여 만들어 보겠습니다. 상단에는 한달 단위로 그래프를 보여주고, 하단에는 해당일의 바이오리듬 정보를 보여 줍니다. 그리고 생일설정을 저장할 수 있도록 하겠습니다. 하단 버튼들의 기능은 아래와 같습니다.
한가지 오류가 있습니다. 생일설정 시에 기존의 저장된 날짜가 DatePicker에 설정되지 않습니다. 값은 정확한데 보여지는 부분은 minimumDate로 초기에 선택되어져 있는 것 같습니다. 검색을 해봐도 같은 증상을 겪은 경우는 보았는데, 원인과 해결책은 찾지 못했습니다.
- << : 한달 전으로 이동
- < : 하루 전으로 이동
- > : 하루 후로 이동
- >> : 한달 후로 이동
- i : 생일 설정
한가지 오류가 있습니다. 생일설정 시에 기존의 저장된 날짜가 DatePicker에 설정되지 않습니다. 값은 정확한데 보여지는 부분은 minimumDate로 초기에 선택되어져 있는 것 같습니다. 검색을 해봐도 같은 증상을 겪은 경우는 보았는데, 원인과 해결책은 찾지 못했습니다.
완성된 모습은 아래와 같습니다.

1. 프로젝트 생성

Unility Application은 컨텐츠를 보여주는 main view와 설정등을 할 수 있는 flipside view를 제공하며, 두 뷰의 변환시에 아래와 같은 에니메이션 효과를 제공합니다.


2. 소스코드
1) Global.h

#define MAX_DATATYPE 3
#define US_BIRTHYEAR_KEY @"birth_year"
#define US_BIRTHMONTH_KEY @"birth_month"
#define US_BIRTHDAY_KEY @"birth_day"
#define NM_BIRTHDAYCHANGED @"NTBirthdayChanged"
#define NAV_PREVMONTH 1
#define NAV_PREVDAY 2
#define NAV_NEXTDAY 3
#define NAV_NEXTMONTH 4
#define ONEDAY_SECOND (24 * 60 * 60)
#define US_BIRTHYEAR_KEY @"birth_year"
#define US_BIRTHMONTH_KEY @"birth_month"
#define US_BIRTHDAY_KEY @"birth_day"
#define NM_BIRTHDAYCHANGED @"NTBirthdayChanged"
#define NAV_PREVMONTH 1
#define NAV_PREVDAY 2
#define NAV_NEXTDAY 3
#define NAV_NEXTMONTH 4
#define ONEDAY_SECOND (24 * 60 * 60)
2) GraphView
그래프를 출력하기 위한 View를 생성합니다. 메뉴에서 File/New File...을 클릭 후에 iPhone OS/Cocoa Touch Classes 항목에서 UIView subclass를 선택한 후에 Next 버튼을 클릭합니다. 파일명에 GraphView.m을 입력한 후에 저장합니다.
* GraphView.h
#import <UIKit/UIKit.h>
@interface GraphView : UIView {
UIImage *backgroundImage;
NSDateComponents *currentDate;
NSDateComponents *birthDate;
float biorhythmData[31][MAX_DATATYPE];
}
@property (nonatomic, retain) NSDateComponents *currentDate;
@property (nonatomic, retain) NSDateComponents *birthDate;
- (void)setBirthDate:(int)year atMonth:(int)month atDay:(int)day;
- (void)setCurrentDate:(int)year atMonth:(int)month atDay:(int)day;
- (void)changeDate:(int)pos;
- (NSDateComponents *)currentDate;
- (void)resetBiorhythmData;
- (float *)getBiorhythmDayData:(int)day;
@end
@interface GraphView : UIView {
UIImage *backgroundImage;
NSDateComponents *currentDate;
NSDateComponents *birthDate;
float biorhythmData[31][MAX_DATATYPE];
}
@property (nonatomic, retain) NSDateComponents *currentDate;
@property (nonatomic, retain) NSDateComponents *birthDate;
- (void)setBirthDate:(int)year atMonth:(int)month atDay:(int)day;
- (void)setCurrentDate:(int)year atMonth:(int)month atDay:(int)day;
- (void)changeDate:(int)pos;
- (NSDateComponents *)currentDate;
- (void)resetBiorhythmData;
- (float *)getBiorhythmDayData:(int)day;
@end
* GraphView.m
#import "Global.h"
#import "GraphView.h"
@implementation GraphView
@synthesize currentDate;
@synthesize birthDate;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)awakeFromNib {
currentDate = [[NSDateComponents alloc] init];
/* 배경 이미지로 사용할 bio.png 로드 */
backgroundImage = [[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"bio" ofType:@"png"]];
}
- (void)drawRect:(CGRect)rect {
#define START_X 17 // 그래프 시작 X 위치
#define START_Y 22 // 그래프 시작 Y 위치
#define DAY_WIDTH 10 // 일별 간격
#define BOTTOM_HEIGHT 4 // 하단 공백 높이
/* 데이터별 색상 테이블 */
static const CGFloat color[MAX_DATATYPE][5] = {
{ 1.0, 0.0, 0.0, 1.0 }, //red
{ 0.0, 1.0, 0.0, 1.0 }, //green
{ 0.0, 0.0, 1.0, 1.0 } //blue
};
CGSize viewSize = rect.size;
CGContextRef context = UIGraphicsGetCurrentContext();
/* 배경 이미지 출력 */
CGPoint point;
point.x = point.y = 0;
[backgroundImage drawAtPoint:point];
/* 오늘 날짜를 가르키는 위치는 노란 선으로 출력 */
CGContextBeginPath(context);
CGContextSetLineWidth(context, 1.0);
CGContextSetRGBStrokeColor(context, 1.0, 0.8, 0.0, 1.0);
CGContextMoveToPoint(context, START_X + (DAY_WIDTH * ([currentDate day] - 1)), START_Y);
CGContextAddLineToPoint(context, START_X + (DAY_WIDTH * ([currentDate day] - 1)), viewSize.height - BOTTOM_HEIGHT);
CGContextStrokePath(context);
/* 바이오리듬 출력 */
int i, j;
int lineX = START_X;
int vcenter = START_Y + (viewSize.height - START_Y - BOTTOM_HEIGHT)/2; // 그래프의 Y 중간 좌표
/* 바이오리듬 출력 */
for (i = 1; i < 31; i++) {
for(j = 0; j < MAX_DATATYPE; j++) {
CGContextBeginPath(context);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColor(context, color[j]);
CGContextMoveToPoint(context, lineX, vcenter - biorhythmData[i-1][j]);
CGContextAddLineToPoint(context, lineX + DAY_WIDTH, vcenter - biorhythmData[i][j]);
CGContextStrokePath(context);
}
lineX += DAY_WIDTH;
}
}
- (void)dealloc {
[backgroundImage release];
[currentDate release];
[super dealloc];
}
- (void)resetBiorhythmData {
static const double s_values[MAX_DATATYPE] = {
23.0, 33.0, 28.0 // 신체, 지성, 감성
};
/* 현재 설정된 날짜의 1일 부터 생일 사이의 날수를 구한다. */
NSDateComponents *firstDate = [[NSDateComponents alloc] init];
[firstDate setYear: [currentDate year]];
[firstDate setMonth: [currentDate month]];
[firstDate setDay:1];
NSDate *tempDay = [[NSCalendar currentCalendar] dateFromComponents:firstDate];
NSDate *birthDay = [[NSCalendar currentCalendar] dateFromComponents:birthDate];
NSTimeInterval ti = [tempDay timeIntervalSinceDate:birthDay];
[firstDate release];
/* 바이오리듬 데이터를 구한다 */
double days = ceil(fabs(ti) / ONEDAY_SECOND);
for (int i = 0; i < 31; i++) {
for(int j = 0; j < MAX_DATATYPE; j++) {
biorhythmData[i][j] = sin((days/s_values[j]) * 2 * 3.14195) * 100;
}
days += 1.0;
}
/* 변경된 데이터로 다시 그림 */
[self setNeedsDisplay];
}
/* 현재 날짜 변경 */
- (void)setCurrentDate:(int)year atMonth:(int)month atDay:(int)day {
[currentDate setYear:year];
[currentDate setMonth:month];
[currentDate setDay:day];
}
/* 생일 변경 */
- (void)setBirthDate:(int)year atMonth:(int)month atDay:(int)day {
[birthDate setYear:year];
[birthDate setMonth:month];
[birthDate setDay:day];
NSLog(@"SET BIRTHDAY: %d, %d, %d", year, month, day);
}
/* 사용자가 버튼을 클릭했을 때, 날짜를 변경한다 */
- (void)changeDate:(int)pos {
NSRange monthRange;
NSTimeInterval newValue = 0;
NSDate *tempDate = [[NSCalendar currentCalendar] dateFromComponents:currentDate];
if (pos == NAV_PREVMONTH) {
/* 이전 달로 이동을 위해 이전 달의 날수를 구한다 */
NSDateComponents *prevMonthDate = [[NSDateComponents alloc] init];
[prevMonthDate setYear: [currentDate year]];
[prevMonthDate setMonth: [currentDate month]-1];
[prevMonthDate setDay:1];
monthRange = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[[NSCalendar currentCalendar] dateFromComponents:prevMonthDate]];
[prevMonthDate release];
/* 한달 전으로 이동 */
newValue = ONEDAY_SECOND * monthRange.length;
newValue = -newValue;
}
else if (pos == NAV_PREVDAY) {
/* 하루 전으로 이동 */
newValue = -ONEDAY_SECOND;
}
else if (pos == NAV_NEXTDAY) {
/* 하루 후로 이동 */
newValue = ONEDAY_SECOND;
}
else if (pos == NAV_NEXTMONTH) {
/* 다음 달로 이동을 위해 현재 달의 날수를 구한다 */
monthRange = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[[NSCalendar currentCalendar] dateFromComponents:currentDate]];
/* 한달 후로 이동 */
newValue = ONEDAY_SECOND * monthRange.length;
}
/* 날짜를 변경하고 변경된 날짜를 구한다. */
NSDateComponents *newDate = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[tempDate addTimeInterval:newValue]];
/* 현재 날짜를 변경 */
[currentDate setYear: [newDate year]];
[currentDate setMonth: [newDate month]];
[currentDate setDay: [newDate day]];
/* 바이오리듬을 다시 계산하고 출력한다. */
[self resetBiorhythmData];
}
- (float *)getBiorhythmDayData:(int)day {
return biorhythmData[day-1];
}
- (NSDateComponents *)currentDate {
return currentDate;
}
@end
#import "GraphView.h"
@implementation GraphView
@synthesize currentDate;
@synthesize birthDate;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)awakeFromNib {
currentDate = [[NSDateComponents alloc] init];
/* 배경 이미지로 사용할 bio.png 로드 */
backgroundImage = [[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:@"bio" ofType:@"png"]];
}
- (void)drawRect:(CGRect)rect {
#define START_X 17 // 그래프 시작 X 위치
#define START_Y 22 // 그래프 시작 Y 위치
#define DAY_WIDTH 10 // 일별 간격
#define BOTTOM_HEIGHT 4 // 하단 공백 높이
/* 데이터별 색상 테이블 */
static const CGFloat color[MAX_DATATYPE][5] = {
{ 1.0, 0.0, 0.0, 1.0 }, //red
{ 0.0, 1.0, 0.0, 1.0 }, //green
{ 0.0, 0.0, 1.0, 1.0 } //blue
};
CGSize viewSize = rect.size;
CGContextRef context = UIGraphicsGetCurrentContext();
/* 배경 이미지 출력 */
CGPoint point;
point.x = point.y = 0;
[backgroundImage drawAtPoint:point];
/* 오늘 날짜를 가르키는 위치는 노란 선으로 출력 */
CGContextBeginPath(context);
CGContextSetLineWidth(context, 1.0);
CGContextSetRGBStrokeColor(context, 1.0, 0.8, 0.0, 1.0);
CGContextMoveToPoint(context, START_X + (DAY_WIDTH * ([currentDate day] - 1)), START_Y);
CGContextAddLineToPoint(context, START_X + (DAY_WIDTH * ([currentDate day] - 1)), viewSize.height - BOTTOM_HEIGHT);
CGContextStrokePath(context);
/* 바이오리듬 출력 */
int i, j;
int lineX = START_X;
int vcenter = START_Y + (viewSize.height - START_Y - BOTTOM_HEIGHT)/2; // 그래프의 Y 중간 좌표
/* 바이오리듬 출력 */
for (i = 1; i < 31; i++) {
for(j = 0; j < MAX_DATATYPE; j++) {
CGContextBeginPath(context);
CGContextSetLineWidth(context, 2.0);
CGContextSetStrokeColor(context, color[j]);
CGContextMoveToPoint(context, lineX, vcenter - biorhythmData[i-1][j]);
CGContextAddLineToPoint(context, lineX + DAY_WIDTH, vcenter - biorhythmData[i][j]);
CGContextStrokePath(context);
}
lineX += DAY_WIDTH;
}
}
- (void)dealloc {
[backgroundImage release];
[currentDate release];
[super dealloc];
}
- (void)resetBiorhythmData {
static const double s_values[MAX_DATATYPE] = {
23.0, 33.0, 28.0 // 신체, 지성, 감성
};
/* 현재 설정된 날짜의 1일 부터 생일 사이의 날수를 구한다. */
NSDateComponents *firstDate = [[NSDateComponents alloc] init];
[firstDate setYear: [currentDate year]];
[firstDate setMonth: [currentDate month]];
[firstDate setDay:1];
NSDate *tempDay = [[NSCalendar currentCalendar] dateFromComponents:firstDate];
NSDate *birthDay = [[NSCalendar currentCalendar] dateFromComponents:birthDate];
NSTimeInterval ti = [tempDay timeIntervalSinceDate:birthDay];
[firstDate release];
/* 바이오리듬 데이터를 구한다 */
double days = ceil(fabs(ti) / ONEDAY_SECOND);
for (int i = 0; i < 31; i++) {
for(int j = 0; j < MAX_DATATYPE; j++) {
biorhythmData[i][j] = sin((days/s_values[j]) * 2 * 3.14195) * 100;
}
days += 1.0;
}
/* 변경된 데이터로 다시 그림 */
[self setNeedsDisplay];
}
/* 현재 날짜 변경 */
- (void)setCurrentDate:(int)year atMonth:(int)month atDay:(int)day {
[currentDate setYear:year];
[currentDate setMonth:month];
[currentDate setDay:day];
}
/* 생일 변경 */
- (void)setBirthDate:(int)year atMonth:(int)month atDay:(int)day {
[birthDate setYear:year];
[birthDate setMonth:month];
[birthDate setDay:day];
NSLog(@"SET BIRTHDAY: %d, %d, %d", year, month, day);
}
/* 사용자가 버튼을 클릭했을 때, 날짜를 변경한다 */
- (void)changeDate:(int)pos {
NSRange monthRange;
NSTimeInterval newValue = 0;
NSDate *tempDate = [[NSCalendar currentCalendar] dateFromComponents:currentDate];
if (pos == NAV_PREVMONTH) {
/* 이전 달로 이동을 위해 이전 달의 날수를 구한다 */
NSDateComponents *prevMonthDate = [[NSDateComponents alloc] init];
[prevMonthDate setYear: [currentDate year]];
[prevMonthDate setMonth: [currentDate month]-1];
[prevMonthDate setDay:1];
monthRange = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[[NSCalendar currentCalendar] dateFromComponents:prevMonthDate]];
[prevMonthDate release];
/* 한달 전으로 이동 */
newValue = ONEDAY_SECOND * monthRange.length;
newValue = -newValue;
}
else if (pos == NAV_PREVDAY) {
/* 하루 전으로 이동 */
newValue = -ONEDAY_SECOND;
}
else if (pos == NAV_NEXTDAY) {
/* 하루 후로 이동 */
newValue = ONEDAY_SECOND;
}
else if (pos == NAV_NEXTMONTH) {
/* 다음 달로 이동을 위해 현재 달의 날수를 구한다 */
monthRange = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
inUnit:NSMonthCalendarUnit
forDate:[[NSCalendar currentCalendar] dateFromComponents:currentDate]];
/* 한달 후로 이동 */
newValue = ONEDAY_SECOND * monthRange.length;
}
/* 날짜를 변경하고 변경된 날짜를 구한다. */
NSDateComponents *newDate = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[tempDate addTimeInterval:newValue]];
/* 현재 날짜를 변경 */
[currentDate setYear: [newDate year]];
[currentDate setMonth: [newDate month]];
[currentDate setDay: [newDate day]];
/* 바이오리듬을 다시 계산하고 출력한다. */
[self resetBiorhythmData];
}
- (float *)getBiorhythmDayData:(int)day {
return biorhythmData[day-1];
}
- (NSDateComponents *)currentDate {
return currentDate;
}
@end
3) MainView
* MainView.h
#import <UIKit/UIKit.h>
@interface MainView : UIView {
UIImage *barFrame[MAX_DATATYPE];
double bioData[MAX_DATATYPE];
}
-(void)setData:(int)value1 secondValue:(int)value2 thirdValue:(int)value2;
@end
@interface MainView : UIView {
UIImage *barFrame[MAX_DATATYPE];
double bioData[MAX_DATATYPE];
}
-(void)setData:(int)value1 secondValue:(int)value2 thirdValue:(int)value2;
@end
* MainView.m
#import "Global.h"
#import "MainView.h"
@implementation MainView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)awakeFromNib {
/* 바의 배경을 위한 이미지를 로드한다. */
for (int i = 1; i <= MAX_DATATYPE; i++) {
barFrame[i - 1] = [[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"frame%d", i] ofType:@"png"]];
}
}
- (void)drawRect:(CGRect)rect {
#define CENTER_X 210 // 바의 중간(0) 위치
#define START_Y 300 // 바가 출력될 Y 위치
#define START_X 120 // 바가 출력될 X 위치
#define BAR_HEIGHT 14.0 // 바의 높이
#define BAR_SPACE 40 // 각 바간 간격
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
int y = START_Y + 15;
CGPoint point;
point.y = START_Y;
point.x = START_X;
for (int i = 0; i < MAX_DATATYPE; i++) {
/* 배경 이미지 출력 */
[barFrame[i] drawAtPoint:point];
CGContextBeginPath(context);
CGContextSetLineWidth(context, BAR_HEIGHT);
/* 바이오리듬 값이 0보다 작으면 붉은 색으로 크면 파란색으로 표시 */
if (bioData[i] > 0)
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
else
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
/* 바를 그린다 */
CGContextMoveToPoint(context, CENTER_X, y);
CGContextAddLineToPoint(context, CENTER_X + (bioData[i] * 80/100) , y);
CGContextStrokePath(context);
/* Y 좌표 변경 */
point.y += BAR_SPACE;
y += BAR_SPACE;
}
}
-(void)setData:(int)value1 secondValue:(int)value2 thirdValue:(int)value3 {
bioData[0] = value1;
bioData[1] = value2;
bioData[2] = value3;
}
- (void)dealloc {
for (int i = 0; i < MAX_DATATYPE; i++) {
[barFrame[i] release];
}
[super dealloc];
}
@end
#import "MainView.h"
@implementation MainView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)awakeFromNib {
/* 바의 배경을 위한 이미지를 로드한다. */
for (int i = 1; i <= MAX_DATATYPE; i++) {
barFrame[i - 1] = [[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"frame%d", i] ofType:@"png"]];
}
}
- (void)drawRect:(CGRect)rect {
#define CENTER_X 210 // 바의 중간(0) 위치
#define START_Y 300 // 바가 출력될 Y 위치
#define START_X 120 // 바가 출력될 X 위치
#define BAR_HEIGHT 14.0 // 바의 높이
#define BAR_SPACE 40 // 각 바간 간격
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
int y = START_Y + 15;
CGPoint point;
point.y = START_Y;
point.x = START_X;
for (int i = 0; i < MAX_DATATYPE; i++) {
/* 배경 이미지 출력 */
[barFrame[i] drawAtPoint:point];
CGContextBeginPath(context);
CGContextSetLineWidth(context, BAR_HEIGHT);
/* 바이오리듬 값이 0보다 작으면 붉은 색으로 크면 파란색으로 표시 */
if (bioData[i] > 0)
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
else
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
/* 바를 그린다 */
CGContextMoveToPoint(context, CENTER_X, y);
CGContextAddLineToPoint(context, CENTER_X + (bioData[i] * 80/100) , y);
CGContextStrokePath(context);
/* Y 좌표 변경 */
point.y += BAR_SPACE;
y += BAR_SPACE;
}
}
-(void)setData:(int)value1 secondValue:(int)value2 thirdValue:(int)value3 {
bioData[0] = value1;
bioData[1] = value2;
bioData[2] = value3;
}
- (void)dealloc {
for (int i = 0; i < MAX_DATATYPE; i++) {
[barFrame[i] release];
}
[super dealloc];
}
@end
4) MainViewController
* MainViewController.h
#import <UIKit/UIKit.h>
@class GraphView;
@class MainView;
@interface MainViewController : UIViewController {
IBOutlet MainView *mainView;
IBOutlet GraphView *graphView;
IBOutlet UITextField *value_1;
IBOutlet UITextField *value_2;
IBOutlet UITextField *value_3;
IBOutlet UIBarButtonItem *currentDate;
}
- (void)updateInfoUI;
- (void)birthdayChanged:(NSNotification *)note;
- (IBAction)navigationButtonClicked:(id)sender;
@end
@class GraphView;
@class MainView;
@interface MainViewController : UIViewController {
IBOutlet MainView *mainView;
IBOutlet GraphView *graphView;
IBOutlet UITextField *value_1;
IBOutlet UITextField *value_2;
IBOutlet UITextField *value_3;
IBOutlet UIBarButtonItem *currentDate;
}
- (void)updateInfoUI;
- (void)birthdayChanged:(NSNotification *)note;
- (IBAction)navigationButtonClicked:(id)sender;
@end
* MainViewController.m
#import "Global.h"
#import "MainViewController.h"
#import "MainView.h"
#import "GraphView.h"
@implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
/* 오늘 날짜를 구한다. */
NSDateComponents *today = [[NSCalendar currentCalendar]
components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[NSDate date]];
/* 현재 날짜 설정 */
[graphView setCurrentDate:[today year]
atMonth:[today month]
atDay:[today day]];
/* 생년월일 설정 */
[graphView setBirthDate:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHYEAR_KEY]
atMonth:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHMONTH_KEY]
atDay:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHDAY_KEY]];
/* 그래프를 그리고 UI를 설정한다. */
[graphView resetBiorhythmData];
[self updateInfoUI];
/* 환경설정에서 생일이 변경되었을 때를 위해 옵저버로 등록 */
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(birthdayChanged:)
name:NM_BIRTHDAYCHANGED
object:nil];
}
- (void)updateInfoUI {
/* 하단 타이틀에 현재 날짜를 출력 */
NSDateComponents *date = [graphView currentDate];
[currentDate setTitle:[NSString stringWithFormat:@"%d.%02d.%02d",
[date year], [date month], [date day]]];
float *bioValue = [graphView getBiorhythmDayData:[date day]];
int value1 = (int)ceil(bioValue[0]);
int value2 = (int)ceil(bioValue[1]);
int value3 = (int)ceil(bioValue[2]);
/* 각 바이오리듬 값 출력 */
[value_1 setText:[NSString stringWithFormat:@"%d", value1]];
[value_2 setText:[NSString stringWithFormat:@"%d", value2]];
[value_3 setText:[NSString stringWithFormat:@"%d", value3]];
/* mainView에 현재 설정된 값을 알려주고, 바가 다시 그려지도록 한다. */
[mainView setData:value1 secondValue:value2 thirdValue:value3];
[mainView setNeedsDisplay];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
- (void)birthdayChanged:(NSNotification *)note
{
/* 생일이 변경되었을 때 다시 설정하고 그려지도록 한다. */
[graphView setBirthDate:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHYEAR_KEY]
atMonth:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHMONTH_KEY]
atDay:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHDAY_KEY]];
[graphView resetBiorhythmData];
[self updateInfoUI];
}
- (IBAction) navigationButtonClicked:(id)sender {
/* 사용자가 날짜 이동 버튼을 클릭하였을 경우 처리 */
[graphView changeDate:[sender tag]];
[self updateInfoUI];
}
@end
#import "MainViewController.h"
#import "MainView.h"
#import "GraphView.h"
@implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
/* 오늘 날짜를 구한다. */
NSDateComponents *today = [[NSCalendar currentCalendar]
components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[NSDate date]];
/* 현재 날짜 설정 */
[graphView setCurrentDate:[today year]
atMonth:[today month]
atDay:[today day]];
/* 생년월일 설정 */
[graphView setBirthDate:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHYEAR_KEY]
atMonth:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHMONTH_KEY]
atDay:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHDAY_KEY]];
/* 그래프를 그리고 UI를 설정한다. */
[graphView resetBiorhythmData];
[self updateInfoUI];
/* 환경설정에서 생일이 변경되었을 때를 위해 옵저버로 등록 */
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(birthdayChanged:)
name:NM_BIRTHDAYCHANGED
object:nil];
}
- (void)updateInfoUI {
/* 하단 타이틀에 현재 날짜를 출력 */
NSDateComponents *date = [graphView currentDate];
[currentDate setTitle:[NSString stringWithFormat:@"%d.%02d.%02d",
[date year], [date month], [date day]]];
float *bioValue = [graphView getBiorhythmDayData:[date day]];
int value1 = (int)ceil(bioValue[0]);
int value2 = (int)ceil(bioValue[1]);
int value3 = (int)ceil(bioValue[2]);
/* 각 바이오리듬 값 출력 */
[value_1 setText:[NSString stringWithFormat:@"%d", value1]];
[value_2 setText:[NSString stringWithFormat:@"%d", value2]];
[value_3 setText:[NSString stringWithFormat:@"%d", value3]];
/* mainView에 현재 설정된 값을 알려주고, 바가 다시 그려지도록 한다. */
[mainView setData:value1 secondValue:value2 thirdValue:value3];
[mainView setNeedsDisplay];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
- (void)birthdayChanged:(NSNotification *)note
{
/* 생일이 변경되었을 때 다시 설정하고 그려지도록 한다. */
[graphView setBirthDate:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHYEAR_KEY]
atMonth:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHMONTH_KEY]
atDay:[[NSUserDefaults standardUserDefaults] integerForKey:US_BIRTHDAY_KEY]];
[graphView resetBiorhythmData];
[self updateInfoUI];
}
- (IBAction) navigationButtonClicked:(id)sender {
/* 사용자가 날짜 이동 버튼을 클릭하였을 경우 처리 */
[graphView changeDate:[sender tag]];
[self updateInfoUI];
}
@end
5) FlipsideViewController
* FlipsideViewController.h
#import <UIKit/UIKit.h>
@interface FlipsideViewController : UIViewController {
IBOutlet UIDatePicker *datePicker;
}
@property (nonatomic, retain) UIDatePicker *datePicker;
@end
@interface FlipsideViewController : UIViewController {
IBOutlet UIDatePicker *datePicker;
}
@property (nonatomic, retain) UIDatePicker *datePicker;
@end
* FlipsideViewController.m
#import "FlipsideViewController.h"
@implementation FlipsideViewController
@synthesize datePicker;
- (void)viewDidLoad {
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
@end
@implementation FlipsideViewController
@synthesize datePicker;
- (void)viewDidLoad {
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
@end
5) RootViewController
* RootViewController.m
#import "Global.h"
#import "RootViewController.h"
#import "MainViewController.h"
#import "FlipsideViewController.h"
@implementation RootViewController
@synthesize infoButton;
@synthesize flipsideNavigationBar;
@synthesize mainViewController;
@synthesize flipsideViewController;
- (void)viewDidLoad {
MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
self.mainViewController = viewController;
[viewController release];
[self.view insertSubview:mainViewController.view belowSubview:infoButton];
}
- (void)loadFlipsideViewController {
FlipsideViewController *viewController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil];
self.flipsideViewController = viewController;
[viewController release];
// Set up the navigation bar
UINavigationBar *aNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)];
aNavigationBar.barStyle = UIBarStyleBlackOpaque;
self.flipsideNavigationBar = aNavigationBar;
[aNavigationBar release];
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"iBiorhythm"];
navigationItem.rightBarButtonItem = buttonItem;
[flipsideNavigationBar pushNavigationItem:navigationItem animated:NO];
[navigationItem release];
[buttonItem release];
}
- (IBAction)toggleView {
if (flipsideViewController == nil) {
[self loadFlipsideViewController];
}
UIView *mainView = mainViewController.view;
UIView *flipsideView = flipsideViewController.view;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES];
if ([mainView superview] != nil) {
[flipsideViewController viewWillAppear:YES];
[mainViewController viewWillDisappear:YES];
[mainView removeFromSuperview];
[infoButton removeFromSuperview];
[self.view addSubview:flipsideView];
[self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView];
[mainViewController viewDidDisappear:YES];
[flipsideViewController viewDidAppear:YES];
/* DataPicker 날짜를 저장된 날짜로 설정 (현재 동작하지 않음) */
NSDateComponents *curDate = [[NSDateComponents alloc] init];
int year = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
int month = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
int day = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
[curDate setYear: year];
[curDate setMonth: month];
[curDate setDay: day];
NSDate *tempDate = [[NSCalendar currentCalendar] dateFromComponents:curDate];
[[flipsideViewController datePicker] setDate:tempDate animated:YES];
[curDate release];
} else {
[mainViewController viewWillAppear:YES];
[flipsideViewController viewWillDisappear:YES];
[flipsideView removeFromSuperview];
[flipsideNavigationBar removeFromSuperview];
[self.view addSubview:mainView];
[self.view insertSubview:infoButton aboveSubview:mainViewController.view];
[flipsideViewController viewDidDisappear:YES];
[mainViewController viewDidAppear:YES];
/* 사용자가 설정한 날짜(생일)를 저장 한다 */
NSDateComponents *newDate = [[NSCalendar currentCalendar]
components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[[flipsideViewController datePicker] date]];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate year] forKey:US_BIRTHYEAR_KEY];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate month] forKey:US_BIRTHMONTH_KEY];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate day] forKey:US_BIRTHDAY_KEY];
/* 바이오리듬이 변경되도록 메시지를 보낸다. */
[[NSNotificationCenter defaultCenter]
postNotificationName:NM_BIRTHDAYCHANGED
object:self];
}
[UIView commitAnimations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[infoButton release];
[flipsideNavigationBar release];
[mainViewController release];
[flipsideViewController release];
[super dealloc];
}
@end
#import "RootViewController.h"
#import "MainViewController.h"
#import "FlipsideViewController.h"
@implementation RootViewController
@synthesize infoButton;
@synthesize flipsideNavigationBar;
@synthesize mainViewController;
@synthesize flipsideViewController;
- (void)viewDidLoad {
MainViewController *viewController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
self.mainViewController = viewController;
[viewController release];
[self.view insertSubview:mainViewController.view belowSubview:infoButton];
}
- (void)loadFlipsideViewController {
FlipsideViewController *viewController = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil];
self.flipsideViewController = viewController;
[viewController release];
// Set up the navigation bar
UINavigationBar *aNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)];
aNavigationBar.barStyle = UIBarStyleBlackOpaque;
self.flipsideNavigationBar = aNavigationBar;
[aNavigationBar release];
UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(toggleView)];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"iBiorhythm"];
navigationItem.rightBarButtonItem = buttonItem;
[flipsideNavigationBar pushNavigationItem:navigationItem animated:NO];
[navigationItem release];
[buttonItem release];
}
- (IBAction)toggleView {
if (flipsideViewController == nil) {
[self loadFlipsideViewController];
}
UIView *mainView = mainViewController.view;
UIView *flipsideView = flipsideViewController.view;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:([mainView superview] ? UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransitionFlipFromLeft) forView:self.view cache:YES];
if ([mainView superview] != nil) {
[flipsideViewController viewWillAppear:YES];
[mainViewController viewWillDisappear:YES];
[mainView removeFromSuperview];
[infoButton removeFromSuperview];
[self.view addSubview:flipsideView];
[self.view insertSubview:flipsideNavigationBar aboveSubview:flipsideView];
[mainViewController viewDidDisappear:YES];
[flipsideViewController viewDidAppear:YES];
/* DataPicker 날짜를 저장된 날짜로 설정 (현재 동작하지 않음) */
NSDateComponents *curDate = [[NSDateComponents alloc] init];
int year = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
int month = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
int day = [[NSUserDefaults standardUserDefaults] integerForKey:@"birth_year"];
[curDate setYear: year];
[curDate setMonth: month];
[curDate setDay: day];
NSDate *tempDate = [[NSCalendar currentCalendar] dateFromComponents:curDate];
[[flipsideViewController datePicker] setDate:tempDate animated:YES];
[curDate release];
} else {
[mainViewController viewWillAppear:YES];
[flipsideViewController viewWillDisappear:YES];
[flipsideView removeFromSuperview];
[flipsideNavigationBar removeFromSuperview];
[self.view addSubview:mainView];
[self.view insertSubview:infoButton aboveSubview:mainViewController.view];
[flipsideViewController viewDidDisappear:YES];
[mainViewController viewDidAppear:YES];
/* 사용자가 설정한 날짜(생일)를 저장 한다 */
NSDateComponents *newDate = [[NSCalendar currentCalendar]
components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[[flipsideViewController datePicker] date]];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate year] forKey:US_BIRTHYEAR_KEY];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate month] forKey:US_BIRTHMONTH_KEY];
[[NSUserDefaults standardUserDefaults] setInteger:[newDate day] forKey:US_BIRTHDAY_KEY];
/* 바이오리듬이 변경되도록 메시지를 보낸다. */
[[NSNotificationCenter defaultCenter]
postNotificationName:NM_BIRTHDAYCHANGED
object:self];
}
[UIView commitAnimations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[infoButton release];
[flipsideNavigationBar release];
[mainViewController release];
[flipsideViewController release];
[super dealloc];
}
@end
다음 포스팅에선 인터페이스 빌더에서 작업을 하고 어플리케이션이 동작하도록 완성시켜 보겠습니다. 동작은 하는데 제대로 만든 것인지는 모르겠습니다.
'iOS' 카테고리의 다른 글
iPhone 어플리케이션 아이콘 설정 (8) | 2008.09.11 |
---|---|
iPhone용 바이오리듬 어플리케이션 만들기 (2-2) (14) | 2008.09.10 |
iPhone용 바이오리듬 어플리케이션 만들기 (1) (27) | 2008.09.04 |
iPhone SDK 둘러보기 (10) | 2008.05.26 |
iPhone SDK 발표 (4) | 2008.03.08 |