iBlogging NRG

CoCoA Cooking Kitchen!


21 Apr

Calendar View Control for iPhone


Some days ago when I was developing an application for iPhone, I required a calendar view to show date specific data on it. Unfortunately I did not find any built-in control in Cocoa Touch UIKit. I was googling to find out any third-party solution but luck did not favored me on that as well. So I decided to create my own calendar control. This article shows you how to use it in your applications.
The calendar control that I developed is actually nothing but a view component and if you want  to show any date specific data on it (like event information) then you need separate delegate. The calendar is inherited from UIView and so you can add it as sub-view to other top level view that you want. Follow the steps below to add this and manipulate over this.
1. Create a new view based project in XCode and name it CalTest.
2. In the Classes folder add my NRGUICalendarView.h and NRGUICalendarView.m files.
 
Preview Image
3. You need to add two labels for current month and year and four buttons for navigating around months and years. To contain the calendar view you need to add another sub-view. So you need two outlets for two labels and one outlet for the view and four actions. Add the following code to the CalTestViewController.h file.

#import <UIKit/UIKit.h>

@class NRGUICalendarView;

@interface CalTestViewController : UIViewController {
NRGUICalendarView *cal;
IBOutlet UILabel *monthLabel;
IBOutlet UILabel *yearLabel;
IBOutlet UIView *calCont;
}

@property (nonatomic, retain) IBOutlet UILabel *monthLabel;
@property (nonatomic, retain) IBOutlet UILabel *yearLabel;
@property (nonatomic, retain) IBOutlet UIView *calCont;

- (IBAction)prevMonth:(id)sender;
- (IBAction)nextMonth:(id)sender;
- (IBAction)prevYear:(id)sender;
- (IBAction)nextYear:(id)sender;

@end

4. Now add synthesis and dealloc code to the CalTestViewController.h file.

#import "CalTestViewController.h"
#import "NRGUICalendarView.h"

@implementation CalTestViewController

@synthesize yearLabel, monthLabel, calCont;
————————————————–
————————————————–

- (void)dealloc {
[yearLabel release];
[monthLabel release];
[calCont release];
[super dealloc];
}

5. Now open CalTestViewController.xib in interface builder and add four buttons, two labels and a view to the root view as shown below and the connect all outlets and assign all actions accordingly.

Connecting Outlets and Actions

6. Now add the four navigation actions for months and years in the CalTestViewController.m file.

IBAction)prevMonth:(id)sender {
[cal previousMonth];
monthLabel.text = [cal currentMonthName];
}

- (IBAction)nextMonth:(id)sender {
[cal nextMonth];
monthLabel.text = [cal currentMonthName];
}

- (IBAction)prevYear:(id)sender {
[cal previousYear];
yearLabel.text = [[NSString alloc] initWithFormat:@"%i", [cal currentYear]];
}

- (IBAction)nextYear:(id)sender {
[cal nextYear];
yearLabel.text = [[NSString alloc] initWithFormat:@"%i", [cal currentYear]];
}

7. Add the following initialization code inside the viewDidLoad method of CalTestViewController.m file.

cal = [[NRGUICalendarView alloc] initWithHandler:self];
[calCont addSubview:cal];
monthLabel.text = [cal currentMonthName];
yearLabel.text = [[NSString alloc] initWithFormat:@"%i", [cal currentYear]];

8. Now we need to tell the calendar control that we are going to use the CalTestViewController as its data source and delegate. That’s why we passed self to the initWithHandler message. Now add the following two methods to CalTestViewController.

- (void)daySelected:(id)sender {
}

- (BOOL)isMarked:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {

return NO;

}

Here when the user clicks on any cell in the calendar, the daySelected event is triggered, each cell is implemented by UIButton and the tag of each button is assigned by the month day of the corresponding cell. So if we are interested in the day clicked, we just need to use sender.tag property.
If you want to show marked (colored differently) day (for events etc) you need to return YES from the isMarked:month:day method. The calendar asks the data source delegate if a day is marked while it is being rendered.

9. Now build and run the simulator and you should see something like the following.

Demo

Other methods in NRGUICalendarView class.

- (void)renderYear:(NSInteger)year month:(NSInteger)month;

renders the calendar view to show the specified month.

- (void)gotoYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;

selects the specified cell by day, month, year.

- (void)goToday;

goes and selects the current day.

- (void)previousMonth;

navigates to previous month.

- (void)nextMonth;

navigates to next month.

- (void)previousYear;

navigates to previous year.

- (void)nextYear;

navigates to next year.

- (NSString*)currentMonthName;

returns current month name as string.

- (NSInteger)currentMonth;

returns current month as integer (January = 1, February = 2, and so on).

- (NSInteger)currentYear;

returns current year as integer.

You can buy this class from here.