Working with Cocoa dates objects


Using and mastering dates objects in Cocoa is not so straightforward as it would in other languages (such Java, Actionscript, JavaScript…), where you just rely on a single Date class (ok, latest releases of Java have deprecated this approach, but it was a common practice before as far I know) whose interface provides all the necessary methods to set, get and modify dates and related informations (like years, months, days and so on). Cocoa instead, takes a more sophisticated approach, increasing the flexibility and the power of the framework. Anyway this freedom comes at an obvious price, it requires a little more code to write and additional concepts and classes to learn. Dates are handled using the 5 classes: NSDate, NSCalendar, NSTimeZone, NSDateComponents, NSDateFormatter.


NSDate is the core class that represents a point in time but it’s pretty useless alone, in fact we can create instances of this object but without the ability to configure its details (year, month, day, hours, minutes, seconds…). Its main constructors ([[NSDate alloc] init] and [NSDate date]) return the current date and the only way to initialize a different one (a future or a paste date) with only NSDate is by using previously defined dates passing them to initWithTimeInterval:sinceDate: or dateWithTimeIntervalSinceReferenceDate: otherwise choose among one of the string based constructors that accept string representation of dates (like initWithString: or dateWithString:). NSDate doesn’t provide much more than constructors, the only concrete methods whose interact with date objects are: isEqualToDate:, earlierDate:, laterDate: and compare:. These are used to compare two dates and know which is the earlier and if their are or not the same date. Date computation such finding out years elapsed between two dates, increase a date by an arbitrary amount of days or subtract hours from a date are not possible without using other date-related classes.


NSCalendar represents a system of reckoning time over extended periods and it’s related to a concrete calendar, usually the Gregorian Calendar which is an international standard for civil use. Anyway is possible to initialize an NSCalendar choosing among hebrew, islamic, chinese an others system supported calendars. A nice (not programming related) reading about calendars and their history can be found here:
NSCalendar exposes methods for date computations and to extract date parts (years, months, days…) from a date.
In a calendar, day, week, weekday, month, and year numbers are generally 1-based.


A time zone represents a geopolitical region on Earth that has its own standard time. By convention each time zone computes its local time as an offset from the Greenwich Mean Time (GMT) (
NSTimeZone is a class that handles time zones. A specific time zone can be assigned to an NSCalendar to influence its behavior.


This is a simple abstract class (no more than a structure) that incapsulate date’s parts (year, month, day, hour…). It’s used in conjunction with NSCalendar to initialize a specific user defined NSDate.


This is as special formatter class that handle conversions from date to a string and vice versa by using the conventional unicode date patterns ( NSDateFormatter formats dates according to the defined locale, calendar and time zone, if you don’t specify any of these references it will uses the current system settings.

Common dates tasks

Print a formatted date:

To print a formatted date we have to use NSDateFormatter and specify a formatting mask manually (by using setDateFormat) or rely on the “automatic” masks by choosing among NSDateFormatterStyle styles.

// initialize a date object
NSDate *currentDate = [[NSDate alloc] init];

// initialize a formatter object
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// set formatter's format
[formatter setDateFormat:@"eeee, dd MMMM yyyy - HH:mm"];
// print formatted date
NSLog(@"formatted date: %@", [formatter stringFromDate:currentDate]);

The code above will print “sabato, 13 novembre 2010 – 12:10” on my mac due to my system settings, whose I can check as following:

// get my current time zone
NSLog(@"my time zone: %@ - abbreviation: %@", [[NSTimeZone systemTimeZone] name], [[NSTimeZone systemTimeZone] abbreviation]);
// get my current calendar
NSLog(@"my calendar: %@", [[NSCalendar currentCalendar] calendarIdentifier]);
// get my current locale
NSLog(@"my locale: %@", [[NSLocale currentLocale] localeIdentifier]);

The NSLogs will print:

  • “my time zone: Europe/Rome – abbreviation: GMT+01:00”
  • “my calendar: gregorian”
  • “my locale: it_IT”

Ok, now let’s see how we can influence the formatter by changing locale and time zone:

// create an american locale
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
// assign custom locale to the formatter
[formatter setLocale:usLocale];

// print formatted date
NSLog(@"formatted date: %@", [formatter stringFromDate:currentDate]);

Now it will print: “Saturday, 13 November 2010 – 12:10” despite my system locale is “it_IT”.
To influence date’s hours, I can set a different time zone rather than that one being used by my system:

// set a GMT time zone
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
// print formatted date
NSLog(@"formatted date: %@", [formatter stringFromDate:currentDate]);

Now it will print: “Saturday, 13 November 2010 – 11:10“, in fact my system’s time zone is a “GMT+01:00” and if you subtract that +1 the result is 11 instead of 12!

Create an user defined date:

To create a custom date object (a date with an arbitrary year, month, day and so on), we have first to initialize an instance of NSDateComponents with the desired date’s parts and then use a calendar to retrieve the relative NSDate:

// create a custom dateComponents object
NSDateComponents *customComponents = [[NSDateComponents alloc] init];
[customComponents setYear:2015];
[customComponents setMonth:7];
[customComponents setDay:23];

// create a date object using custom dateComponents against current calendar
NSDate *customDate = [[NSCalendar currentCalendar] dateFromComponents:customComponents];

Get date’s parts from a date

To extract date parts from an NSDate we have to use NSCalendar‘s method components:fromDate:. Components are specified by a flag parameter which can be composed using the bitwise “or” operator (the pipe symbol) and merging NSCalendarUnit constants. To get year, month and day from a date we can do the following:

// get year, month and day parts
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:date];

then we can use retrieved date parts in this way:

NSLog(@"year: %i - month: %i - day: %i", [components year], [components month], [components day]);

It’s important to specify all the date parts we want to use, because if we forget it and we try to access an undefined part, we won’t get an error but instead 2147483647 as the return value (which is the maximum value for a signed 32-bit integer). For example if we write:

NSLog(@"hour: %i", [components hour]);

we will get 2147483647 because we didn’t specify the NSHourCalendarUnit

Add or subtract date parts from/to a date:

To add or subtract date parts from/to a date, we have to create a dateComponents object configuring it with the desired gap to fill and then use calendar’s method dateByAddingComponents:toDate:options:. For example if we want to add 2 years and half to a date we can do this:

// create a dateComponents with 2 years and 6 months
NSDateComponents *newComponents = [[NSDateComponents alloc] init];
[newComponents setYear:2];
[newComponents setMonth:6];

// get a new date by adding components
NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:newComponents toDate:date options:0];

to subtract we have to configure NSDateComponents with negative values (ie: [newComponents setYear:-2]…)

Get difference between two dates:

To get the difference between 2 dates we have to rely on NSCalendar once again and use its components:fromDate:toDate method, by specifying the date parts we are interested in and 2 different dates. Values returned from components can be negative if toDate is earlier than fromDate. The following example retrieve days difference between 2 dates:

NSDateComponents *componentsDiff = [calendar components:NSDayCalendarUnit fromDate:dateA toDate:dateB options:0];


Dates are a fascinating argument when it comes to programming in Objective C, but due to the different aspects involving date computation is really important to understand concepts beyond the mere classes implementations, especially if we want to make internationalized applications. My post would be a synthesis to help you get started faster with dates manipulation, I suggest however to read all the official documentation provided by Apple.

(My) common mistakes learning Objective C and iPhone programming

In this post I would like to gathering all the mistakes I did in the past months while I was learning Objective C, and although I’m still a learner and I will face new obstacles soon, I hope to keep in mind some concepts and language features better, by talking about those and help new students save time on google and extra headache.
So, let’s start with the errors list:

1. No “foo” method found / “foo” may not respond to selector

I was implementing a method (inside .m file) not defined before in the header (.h)

2. Bad positioning and behavior of UITabBarController’s view

I added the UITabBarController’s view to a subview rather than the main window (the only place where you can add it)

3. Create my own null wrapper

Objective C doesn’t allow nil values to be added to collections (NSArray, NSDictionary and so on) but just objects, so I got the smart idea of realize a dummy class representing null values. In this way I can create instances of “MyDummyNullObject” and add them to any kind of collection. However I successively discovered that Cocoa was already providing such class: NSNull! Moreover it offers a better implementation, because it’s a singleton, thus you don’t have to create more than one object but just relay on it’s “factory method”: [NSNull null] which will return the shared NSNull instance.

4. Write repeated @synthetize statemens

There is no need to write “@synthetize” for each class property, we can simple write it once followed by a comma delimited list of properties (ie: @synthetize prop1, prop2, prop3, prop3, prop4;)

5. Create unnecessary pointers for scalar types

Scalar types are basically all that is not a class (NSInteger, NSUInteger, BOOL…), for these types the asterisk is not required! (basically asterisk means: “I’m gonna to create a pointer to an instance of a class”)

6. Try to compare strings and other objects by using == operator

by using == we are not comparing strings values but pointers (which will be always different despite their content). The right way is using isEqualToString:, isEqual: or compare: (and its variants)

7. Check sqlite’s database modifications in the wrong place

I spent a lot of time to figure out why my insert and update commands did not modify database content, then I realized that I was looking at the wrong file! Project’s resources are copied during the build phase, and you can find them under:
“/Users/$user_name/Library/Application Support/iPhone Simulator/$sdk_version/Applications/$app_id/$” (of course you have to replace $foo with your personal info)

8. Initialize variables inside switch/case statement

Is not possible to initialize a variable as first declaration inside a case, if you try to compile the following code:

switch (value) {
    case 5:
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);

The compiler will rise an “Expected expression before NSNumber”. To avoid errors we can simply declare the instance variable before the switch statement in this way:

NSNumber *number;

switch (value) {
    case 5:
        number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);

or cheat the compiler by writing a command like an NSLog, before the assignment:

switch (value) {
    case 5:
        NSLog(@"go on without errors!");
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);

of course this last example is really nonsense, but it gives you the idea :)

As suggested by Dmitry Chestnykh in the comments, there is a better and easy approach to avoid such errors (pay attention to the curly braces in the case):

switch (value) {
    case 5: {
        NSNumber *number = [[NSNumber alloc] initWithInt:value];
        NSLog(@"my number: %i", [number intValue]);

9. Unrecognized selector sent to instance

I was declaring a pointer of type NSMutableArray and assigning it to an NSArray (a simple typo error), in this way:

NSMutableArray *array = [[NSArray alloc] init];

then I was filling it with “addObject”:

[array addObject:myObject];

and at runtime I got the “unrecognized selector sent to instance”, this because I allocated an NSArray which doesn’t have “addObject” among its methods (in fact an NSArray is immutable and objects contained in this collection are specified during its creation)… anyway I don’t understand why the compiler does not rise an error at compile time :^/

10. UITableViewCells mixed up after scrolling UITableView

One of the most complex ui element to understand in the UiKit framework is undoubtedly UITableView, because it’s composed by different elements (like UITableViewCell) and requires a good knowledge of how it has been conceived in order to make it work the right way and with good performance. The main key concept behind this cool component resides in the method “tableView:cellForRowAtIndexPath“. The scope of this one is to return the UITableViewCell for a specific NSIndexPath and is called automatically at runtime. For performance reasons, it should returns cached objects by using dequeueReusableCellWithIdentifier and only if there is no a cached version (the method returns nil), initialize the required cell (that is allocating a UITableViewCell instance and configuring its views). In case of cached cells, you must avoid adding/removing views from the cell and limit changes to colors, label’s values and similar. Any other “invasive” change can results in strange table behavior and performance decrease.