Finishing
the Interface
Unlike some of our
previous projects, the interfaces in this hour are pretty simple (so
that we can focus on the picker itself). We’ll wrap up our work in
Interface Builder by adding a label to the view.
Add the Output Label
Use the Library to add a label (UILabel)
with the title Choose a Date, positioned below the picker. This will be used for
output in the application. For our implementation, we’ve used the
Attributes Inspector to center the text, make it span four lines, set a
font size of 20, and turn on word wrapping. Figure 5 shows the finished interface and attributes for the label.
Connecting to the
Outlet
Connect the label to the outlet differenceResult by control dragging from the File’s Owner icon to
the UILabel within your view or in the
Document window. When prompted, choose the differenceResult
outlet.
The interface is now
complete. Save your work, and then switch back to Xcode for the
implementation.
Implementing the View
Controller Logic
As it turns out, the most
difficult work that we still have in front of us with the date picker
implementation is writing the showDate
logic. To do what we’ve set out to (show the difference between today’s
date and the date in the picker), we need to be able to do several
things:
Before writing showDate, let’s look at the different methods and data types that
we need to complete these tasks.
Getting the Date
To get the current date and
store it in a NSDate object, all that
we need to do is to allocate and initialize a new NSDate. When initialized, it automatically stores
the current date! This means that a single line takes care of our first
hurdle:
todaysDate=[[NSDate alloc] init];
Displaying a Date and
Time
Unfortunately, displaying a
date and time is a bit more tricky than getting the current date. Because we’re going to be
displaying the output in a label (UILabel), we already know how it is going to be
shown on the screen, so the question is really, how do we format a
string with a NSDate object?
Interestingly enough,
there’s a class to handle this for us! We’ll create and initialize an NSDateFormatter
object. Next, we use the object’s setDateFormat to create a custom format using a pattern string. Finally,
we apply that format to our date using another method of NSDateFormatter,
stringFromDate—which, given an NSDate, returns a string in the format that we defined.
For
example, if we assume that we’ve already stored an NSDate in a
variable todaysDate, we can output in a
format like “Month, Day, Year Hour:Minute:Second(AM or PM)” with these
lines:
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MMMM d, yyyy hh:mm:ssa"];
todaysDateString = [dateFormat stringFromDate:todaysDate];
First, the formatter object is
allocated and initialized in a new object, dateFormat. Then the string @"MMMM d, YYYY hh:mm:ssa" is used as a formatting string to set the
format internally in the object. Finally, a new string is returned and
stored in todaysDateString by using the dateFormat
object’s instance method stringFromDate.
Where in the World Did That Date Format String
Come From?
The strings that you can use to
define date formats are defined by a Unicode standard that you can find
here:
For this example, the
patterns are interpreted as follows:
MMMM:
The full name of the month
d: The day of the month, with no
leading zero
YYYY:
The full four-digit year
hh: A two-digit hour (with leading
zero if needed)
mm:
Two digits representing the minute
ss: Two digits representing the
second
a:
AM or PM
Calculating the
Difference Between Two Dates
The last thing that we need to
understand is how to compute the difference between two dates. Instead
of needing any complicated math, we can just use the timeIntervalSinceDate
instance method in an NSDate object.
This method returns the difference between two dates, in seconds. For
example, if we have two NSDate objects, todaysDate and
futureDate, we could calculate the time
in seconds between them with this:
NSTimeInterval difference;
difference = [todaysDate timeIntervalSinceDate:futureDate];
Notice that we store the
result in a variable of type NSTimeInterval.
This isn’t an object. Internally, it is just a double-precision
floating-point number. Typically, this would be declared using the
native C data type double, but Apple
abstracts this from us by using a new type of NSTimeInterval so that we know exactly what to expect out of a
date difference calculation.
By
the Way
Note that
if the timeIntervalSinceDate: method is
given a date before the object that is invoking the method (that is, if futureDate
was before todaysDate in the example), the difference returned is negative;
otherwise, it is positive. To get rid of the negative sign, we’ll be
using the C function fabs(<float>) that, given a
floating-point number, returns its absolute value.
Implementing the Date
Calculation and Display
Putting together all of
these pieces, we should now be able to write the logic for the showDate method. Open the DateCalcViewController.m file in
Xcode and add the following implementation for showDate method
shown in Listing 2.
Listing 2.
1: -(IBAction)showDate:(id)sender { 2: NSDate *todaysDate; 3: NSString *differenceOutput; 4: NSString *todaysDateString; 5: NSDateFormatter *dateFormat; 6: NSTimeInterval difference; 7: 8: 9: todaysDate=[[NSDate alloc] init]; 10: difference = [todaysDate timeIntervalSinceDate:[sender date]] / 86400; 11: 12: dateFormat = [[NSDateFormatter alloc] init]; 13: [dateFormat setDateFormat:@"MMMM d, yyyy hh:mm:ssa"]; 14: todaysDateString = [dateFormat stringFromDate:todaysDate]; 15: 16: differenceOutput=[[NSString alloc] initWithFormat: 17: @"Difference between chosen date and today (%@) in days: %1.2f", 18: todaysDateString,fabs(difference)]; 19: differenceResult.text=differenceOutput; 20: 21: [todaysDate release]; 22: [dateFormat release]; 23: [differenceOutput release]; 24: }
|
Much of this should look
pretty familiar based on the preceding examples, but let’s review the
logic. First, in lines 2–6, we declare the variables we’ll be using: todaysDate
will store the current date, differenceOutput
will be our final formatted string displayed to the user, todaysDateString will contain the formatted version of the
current day’s date, dateFormat
will be our date formatting object, and difference is the double-precision floating-point number used to store
the number of seconds between two dates.
Lines 9 and 10 do most of the
work we set out to accomplish! In line 9, we allocate and initialize todaysDate
as a new NSDate object. The init
automatically stores the current date and time in the object.
In line 10, we use timeIntervalSinceDate to
calculate the time, in seconds, between todaysDate and [sender
date]. Remember that sender will be the date picker
object, and the date method tells an instance of UIDatePicker to return its current date and time in an NSDate object, so this gives our method everything it
needs to work with. The result is divided by 86400
and stored in the difference variable.
Why 86400? This is the number of seconds in a day, so we will be able
to display the number of days between dates, rather than seconds.
In lines 12–14, we
create a new date formatter object (NSDateFormatter) and use it to format todaysDate, storing the results in the string todaysDateString.
Lines 16–18 format the
final output string by allocating a new string (differenceOutput), and then initializing it with initWithFormat. The format string provided includes the
message to be displayed to the user as well as the placeholders %@
and %1.2f—representing a string and a
floating-point number with a leading zero and two decimal places. These
placeholders are replaced with the todaysDateString and the absolute value of the difference
between the dates, fabs(difference).
In line 19, the label we added
to the view, differenceResult, is updated to display differenceOutput.
The last step is to clean up
anything that we allocated in the method, which is accomplished in lines
21–23, where the strings and formatter object are released.
That’s it! Use Build and Run
to run and test your application. You’ve just implemented a date picker,
learned how to perform some basic date arithmetic, and even formatted
dates for output using date formatting strings. What could be better?
Creating your own custom picker with your own data, of course!