Categories
Programming

How to program an iOS text field that takes only numeric input or specific characters with a maximum length [Updated]

Check out this update (May 24, 2016)!

update

The material in this article is still applicable, but you’ll also want to read a newer one titled A better way to program iOS text fields that have maximum lengths and accept or reject specific characters, which shows you how to make text fields that let you specify the following in Interface Builder or using less code:

  • The maximum number of characters that a text field will accept
  • The only characters that can be entered into a text field
  • The only characters that can’t be entered into a text field

I’m already using that material in a couple of projects, and I think you’ll find it handy, too. Check it out!

 

 

 

And now, the original article…

Constraining text fields

constrained text fields demo app

Click the image to see it at full size.

Update, August 26, 2015: I’ve updated this article so that its code works with Swift 2. It compiles under the latest version of Xcode 7, beta 6.

swift kickA little while back, I published an article that covered constraining text fields so that they accepted only values that evaluated to numeric ones, and limited them to a specified maximum number of characters (don’t bother looking for it; it redirects to this article now). This article expands and improves on it by showing you how to create iOS text fields that:

  • accept only numeric values,
  • accept only characters that appear in a specified string,
  • accept any characters except those that appear in a specified string, and
  • combine any of the features listed above

zip file iconIn order to demonstrate this, I’ve created a quick sample app, ConstrainedTextFieldDemo. You can download it here [90K Xcode project and associated files, zipped]. When you run it, you’ll the screen pictured above. It contains a set of text fields, each one with its own set of constraints:

  1. A text field that accepts only vowel characters (upper- and lowercase), and no more than 6 of them.
  2. A text field that accepts any character except vowels, and no more than 8 of them.
  3. A text field that accepts digits only, and no more than 3 of them.
  4. A text field that accepts only numeric values, as long as they’re 7 characters or fewer in length. Note that this field allows numbers in scientific notation.
  5. A text field that accepts only positive integers up to 5 characters in length.

In this article, I’ll walk you through the app and show you how to create your own constrained text fields in iOS. Better still, I’ll give you the project files so that you can experiment with the app.

Cut to the code (and the storyboard, too)!

Before we get into the explanations, let me cut to the chase and just give you the code.

For the purposes of discussing constrained text fields, we need to consider only two files:

  1. The view controller, ViewController.swift, and
  2. a set of string utility methods contained in StringUtils.swift.

Here’s ViewController.swift:

I gave the outlets for the text fields sensible names, but I thought that it might be helpful to show you an annotated storyboard that points out which outlet belongs to which text field:

constrained text fields screenshot

The code in the view controller calls on some string utility methods that I decided to put into their own module: the StringUtils.swift file:

Let’s take a closer look at the code…

The delegate pattern and text fields

The delegate pattern in general

the delegate pattern

The Delegate pattern is a fundamental part of iOS app development. You’ll encounter it often when programming user interfaces, including those times when you want to your program to react to what the user does with text fields.

The delegate pattern involves two categories of object:

  • A delegator, which needs to perform a task, but doesn’t have some needed information, resources, or logic to do so. It gets that needed information, resources, or logic from…
  • A delegate. While it typically can’t do what the delegator does, it has the information, resources, or logic that the delegator needs to perform its task.

My pet analogy for the delegate pattern is pictured above: an airplane and air traffic control. Unlike the driver of a car, who’s controlled only by traffic signals and pretty much free to choose any destination and route s/he pleases, the pilot of a plane has to delegate a lot of those choices to air traffic control. The airplane, which does the actual flying, is the delegator, and air traffic control, which gives clearance for takeoff and landing and tells the plane the heading, speed, and altitude at which it should fly, is the delegate.

The delegate pattern in iOS

If you look at the delegate pattern in Wikipedia, you’ll see that there are a number of ways to implement it. Here’s how it’s done in iOS (and Cocoa), whether you’re doing it in Objective-C or Swift:

delegate pattern in iOS

There are three things in play:

  • The delegator, which keeps a reference to the delegate, which will end up having the task delegated to it,
  • The delegate, which implements the methods and properties used to accomplish the delegated task, and
  • The protocol, which connects the delegator and delegate by:
    • giving the delegator a way to send messages to the delegate, and
    • giving the delegate a way to perform actions on behalf of the delegator.

The delegate pattern with iOS’ text fields

Let’s make the above diagram a little more specific and talk about delegation in terms of iOS’ text fields:

delegation with text fields

iOS text fields — that is, instances of the UITextField class — participate in a delegate pattern as delegators. They’ve got the power to control what happens when the user starts and stops editing their contents and what characters can be typed into them, but they offload the logic that handles those tasks to another object: the delegate.

A specific protocol, the UITextFieldDelegate protocol, connects the text field and its delegate together. A protocol is simply a set of declarations of class members — instance properties, instance methods, type methods, operators, and subscripts. These instance properties, instance methods, type methods, operators, and subscripts are implemented in the delegate (implementing a protocol’s members is called adopting the protocol), and the delegator calls on these implemented members.

The protocol: UITextFieldDelegate

Let’s look at the UITextFieldDelegate protocol. You can actually check it out for yourself; the simplest way is to control-click or right-click on any occurrence of UITextField in your code and then click on Jump to Definition in the contextual menu that appears:

getting to uitextfielddelegate

You’ll be taken to UITextField.h, a header file that allows Swift to connect to the Objective-C code on which UITextField is built. It contains the declarations for all the publicly-accessible parts of UITextField, including the UITextFieldDelegate protocol. You’ll find it near the end of the file. I’ve reproduced it below:

The delegate: ViewController

In order to become a delegate, a class has to adopt the protocol. If you’re familiar with languages like C# and Java, “adopting a protocol” is similar to “implementing an interface”: we add the protocol to a class’ definition, as if we’re inheriting it. In this case, we’ll have the view controller adopt the protocol:

This says that the ViewController class inherits from the UIViewController class and adopts the UITextFieldDelegate protocol. Having the view controller act as the delegate makes sense: it controls the user interface, and the text fields are part of the user interface.

Just as you have to implement the methods in an inherited interface in C# and Java, you have to implement the methods in an adopted protocol in Swift. There is a difference, however: in Swift, you can choose not to implement methods marked as optional.

You may have noticed that all the methods in the UITextFieldDelegate protocol are optional. This means that a delegate that adopts the protocol can implement as many or as few of its methods as necessary. For the purposes of our app, we’re implementing two of them in ViewController:

  • textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool: The text field calls this whenever the user tries to change the contents of a text field, whether by typing in or deleting a character, or by cutting or pasting. The method should return true if the change is to be accepted, and false to reject the change and keep the contents of the text field the way they are. We’ll use it to limit the types of character that can be entered into the view’s text fields and set a maximum the number of characters that can be entered for each field.
  • textFieldShouldReturn(textField: UITextField) -> Bool: The text field calls this whenever the user taps the Return key or its equivalent on the keyboard. We’ll use it to dismiss the keyboard when the user taps Return.

We’ll talk about the implementation of these methods in the next section. We have to take care of the delegators first.

The delegators: the text fields

We’ve got a protocol, and we’ve got a delegate that adopts it. Now we need to set up the delegators, which in this case, are the text fields — we need to tell them who their delegates are. We do this by setting each text field’s delegate property in the initializeTextFields method of the ViewController class:

By setting all the text fields’ delegate properties to self, we’re saying that this class is their delegate. Any events arising from editing the text fields will be handled by this class.

Constraining the text fields

The magic that constrains a text field so that it’s vowels-only, numbers-only and so on happens inside the protocol method with the very long signature, textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool. This method needs to be coded so that it returns true if we want the user’s changes to be accepted (which then updates the text field), or false if we don’t want the user’s changes to be accepted (which leaves the text field unchanged).

Here’s its code:

This method takes three parameters:

  • textField: the text field that either had a character added to or removed from it.
  • range: the range of the characters within the text field that are to be replaced.
  • string: the replacement string.

Does the change add characters?

The first thing the method does is see if the change adds characters to the text field:

  • If the user has typed a character or pasted non-empty text into the text field, string is non-empty and has a length greater than zero. In this case, we’ll want to do more processing.
  • If the user has deleted a character, cut text, or simply moved the insertion point, string is empty and has a length of zero. In this case, we don’t want to do any more processing; removing characters means we don’t have to see if we want to disallow any added character or if the maximum number of characters for the text field has been exceeded. We’ll just exit the method, returning true so that the change still happens, whether it’s a deletion, a cut, or moving the insertion point.

What will the text field look like after the change?

We want to figure out what the text field would contain if the change were allowed. We’ll call that the prospective text, which we’ll assign to a local constant called prospectiveText. We can figure out what the prospective text is by using NSString‘s stringByReplacingCharactersInRange method on the contents of textField.text.

Here’s where we run into a problem:

  • In order to use NSString‘s stringByReplacingCharactersInRange method, we need to convert a Swift String into an NSString.
  • The type of a text field’s text property type isn’t String, but String?. That’s because a text field’s value can either be:
    • a string when it contains at least one character, or
    • nil when it’s empty
  • String can be cast into NSString; String? can’t.

To get around this problem, we’re going to create a String constant called currentText, which we’ll fill as follows:

  • If the text field isn’t empty — that is, if its value isn’t nil — we’ll simply assign currentText the value of textField.text.
  • If the text field is empty — that is, if its value is nil — we’ll assign currenttext the value "", the empty string. There’s a difference between nil (which denotes no value) and the empty string (which is a value, just one that has a length of 0 characters).

Here’s the code:

As we’ll see shortly, having prospectiveText lets us set a maximum number of characters that can be put into a text field.

Taking care of business

Now that we’ve dealt with cases where the change to the text field deletes characters and have created prospectiveText, we can now start constraining text fields. This is handled in the switch statement, which we use to separate the constraining logic for each text field:

The cases for each text field are listed in the order in which they appear onscreen. Let’s look at them one by one:

The “Vowels only” text field

In this text field, we want the user to be able to enter only vowels — the upper- and lower-case versions of the letters a, e, i, o, and u. We also want to limit its contents to a maximum of 6 characters. Here’s the code that does this:

This code makes use of the String extension method containsOnlyCharactersIn, which I defined in StringUtils.swift. It returns true if the String contains only characters in the provided parameter.

If both conditions in the return statement evaluate to trueprospectiveText contains only vowels and has 6 characters or fewer — the method returns true, the change to the text field is allowed, and the text field is updated. If both conditions don’t evaluate to true, the method returns false, the change to the text field is not allowed, and the text field’s contents remain the same.

The “Anything BUT vowels” text field

In this text field, we want the user to be able to enter any character except vowels and limit its contents to a maximum of 8 characters. Here’s the code that does this:

This code is similar to the code for the “Vowels only” text field. The major difference is that it makes use of another String extension method defined in StringUtils.swift: doesNotContainCharactersIn, which returns true if the String doesn’t contain any of the characters in the provided parameter.

The “Digits only” text field

In this text field, we want the user to be able to enter only digits, and no more than three of them at most. Here’s the code that does this:

This code is almost the same as the code for the “Vowels only” text field.

The “Numeric values only” text field

Here’s an interesting one: a text field that accepts only user input that evaluates to a proper numeric value. That means it will accept the following characters:

  • The digits 0 through 9
  • The (negative) symbol
  • The decimal separator, which is either . or , depending on the user’s locale settings
  • The letter e, which is used for numbers specified in scientific notation

Even when limiting the user to these characters, it’s possible for non-numeric values to be entered. Here are a couple of example non-numeric values that we don’t want the user to be able to enter:

  • More than one decimal separator, such as 1.2.3 or 1,2,3, depending on the user’s locale settings
  • The unary minus being placed anywhere other than the start, such as 4-5

We also want to limit the text field to a maximum of 7 characters.

Here’s the code:

This code makes use of the String extension method isNumeric, which I defined in StringUtils.swift. It returns true if the String contains a value that evaluates to a numeric value. It’s powered by NSScanner, a class that’s handy for going through strings and extracting useful data from them, and its scanDecimal method, which returns true if it finds a value that can be evaluated as an NSDecimal value.

If both conditions in the return statement evaluate to trueprospectiveText evaluates to a numeric value and has 7 characters or fewer — the method returns true, the change to the text field is allowed, and the text field is updated. If both conditions don’t evaluate to true, the method returns false, the change to the text field is not allowed, and the text field’s contents remain the same.

The “Positive integers only” text field

This is a more strict version of the “Numeric values only” text field. It requires that anything entered into it needs to evaluate as a proper numeric value, but it also requires that the value be a positive integer and not be stated in scientific notation. It has a maximum length of 5 characters. Here’s the code:

In order to disallow negative numbers, we use the String extension method doesNotContainCharactersIn to block out characters. We disallow scientific notation by using the same method to block out e characters. The tricky part is disallowing the decimal separator, which can be either . or , depending on the user’s locale. We identify it with NSLocale.currentLocale().objectForKey(NSLocaleDecimalSeparator), which we add to the parameter for doesNotContainCharactersIn.

Any other text fields that might be on the screen

Finally, we handle the default case: any other text fields that might be on the screen, which we won’t constrain:

Other UI goodies

This app has a couple of UI features that I’ll cover in a subsequent article:

  • specifying the keyboard for a specific text field,
  • dismissing the keyboard when the user taps the Return key or its equivalent, and
  • dismissing the keyboard when the user taps on the view

It’s all in the code, so if you’d like to jump in and learn how it works on your own, go right ahead!

Resources

zip file iconIn case you missed it, here are the zipped project files for the demo project, ConstrainedTextFieldDemo [90K Xcode project and associated files, zipped].

Categories
Swift Kick

How to work with dates and times in Swift, part one [Updated for Swift 2]

i just want to use dates

Update, August 26, 2015: I’ve updated this article so that its code works with Swift 2. It compiles under the latest version of Xcode 7, beta 6.

swift kickIf you’re just getting started with date and time programming in Swift, chances are that you probably did some Googling, found NSDate and its companion classes in Apple’s documentation and promptly got confused. Let me reassure you that it isn’t your fault. Apple’s Date and Time Programming Guide isn’t set up in the most helpful way, and its examples are in Objective-C, which can throw you off if you’re not familiar with its [instance method] calling syntax.

If you’re coming to Swift from JavaScript, which makes do with a single object type called Date, the idea of having this set of classes just to handle dates and times looks like overkill:

cocoa date time class chart

Click the chart to see it at full size.

This is the first article in a short series on programming dates and times in Swift. It’ll help you make sense of working with NSDate and its companion classes.

What is UTC? (or: “It’s 5 o’clock somewhere!”)

what time is it right now

People who like to drink are fond of saying “Well, it’s five o’clock somewhere!“, and it’s my favorite way of illustrating that what time it is depends on where you are. It’s why we have UTC — Coordinated Universal Time — the “One True Time” on which every other time zone is based. UTC replaced GMT (Greenwich Meridian Time, the time as observed at the Royal Observatory in Greenwich, London), and it doesn’t change for daylight savings. By having this standard, we eliminate the confusion that comes up when discussing times.

While most places have some names to refer to time zones in everyday conversation — such as Pacific, Mountain, Central, and Eastern in North America — the clearest way to indicate time zones is to express them as negative or positive offsets from UTC. For example, the North American time zone known as “Eastern” is 5 hours behind UTC, so it’s expressed as UTC-05:00. There are certain time zones where the offset isn’t whole hours, such as Newfoundland’s, which is UTC-03:30, and Nepal’s, which for some reason is UTC+05:45.

NSDate: Cocoa standard time

When you want to represent a date or time in Cocoa, you do so with an instance of the NSDate class. Here’s a nice, simple description of what NSDate is:

nsdate

When you’re measuring time, you need a reference point. The Gregorian calendar — the one that I’m 99.999999% sure that you’re using right now — uses what is said to be the year of the birth of Christ as its reference point. Your age uses the date of your birth as a reference point. A time trial race uses the time at the start of the race as its reference point.

NSDate‘s reference point is the start of the third millennium: January 1, 2001 at midnight UTC. It stores time as an NSTimeInterval, a 64-bit floating point value representing a number of seconds. Negative values represent a number seconds before January 1, 2001, 00:00 UTC, and positive values represent a number seconds after that time. According to Apple’s documentation, this representation of time “yields sub-millisecond precision over a range of 10,000 years”, which means that an NSDate instance can represent any point in time from about 3000 BC/BCE to 7000 AD/CE.

Here are 4 historical dates, as seen from NSDate‘s perspective:

historical dates nsdate style

There are some consequences to the fact that NSDate treats time as an offset of seconds:

  • All NSDate values refer to both a date and a time. If you want to use an NSDate to store a date only, you ignore the time portion, and vice versa.
  • NSDate has no concept of time zones or any time unit other than seconds. That means you can’t ask it what year, month, day, hour, or minute correspond to the time it’s storing. As far as it’s concerned, there are no calendars; you work with NSDate‘s representation of time, when it’s time to display a date, time, or both, you format it to use the calendar and time zone that’s appropriate for the user.

There’s a method to this madness: it allows us to use and store dates and times in a way that’s independent of calendar systems, time zones, languages, and date formats. As I write this, it’s the year 2015 in the Gregorian calendar, but the Buddhist calendar says it’s 2558, and if you go by the Hebrew Calendar, it’s 5775. I may say it’s 9:45 a.m. as I write this in Tampa, but if you’re in California, it’s 6:45, and if you’re a soldier, you might call it 14:45 Zulu Time. I call the current month January, but you might call it Enero or Janvier. It’s all the same as far as NSDate is concerned, which makes it incredibly flexible.

Creating NSDates without any helper classes: now is easy, other dates ain’t so pretty

Let’s create some NSDates right now. Fire up Xcode, open a new playground, and enter the following code so that it looks like this:

You should see results in the sidebar that look similar to this:

playground 01

If you create an NSDate without any parameters, you get an instance representing the date and time at the moment it was created. That’s what we’ve done by creating the instance named now.

Note that in the sidebar beside line 5, where we created now, the result displayed in the sidebar is Jan 19, 2015, 8:52 AM. While the internal representation of the current time is a 64-bit floating point value, Xcode’s doing us a favor by representing it in a more readable format and using the local time zone. It’s doing this by making use of a date formatter, which we’ll cover later.

In line 6, we’re using the println function to display the default string representation of an NSDate, which is a completely numeric one. It’s more readable than a 64-bit floating point value, but it might not be in the format or time zone (or even the calendar system) that you want. Once again, this output comes courtesy of a date formatter.

Finally, in line 7, we use the timeIntervalSinceReferenceDate property to display now‘s internal representation of the date and time it’s storing: about 443 million seconds after January 1, 2001 at midnight UTC.

Let’s create the dates from the Historical dates, NSDate style picture above. Enter or paste the highlighted code below so that your playground looks like this:

Note my use of the underscore character, _, to act as a “thousands” separator. It’s not required; it just makes large numbers easier to read.

In the sidebar, you should see nicely-formatted dates beside the NSDates you created:

playground 02

Click the screenshot to see it at full size.

NSDate has four initializers for creating specified dates and times:

Initializer Description
init(timeIntervalSinceReferenceDate:) Create an NSDate instance representing a time specified by a number of seconds before or after January 1, 2001 00:00 UTC.
init(timeIntervalSinceNow:) Create an NSDate instance representing a time specified by a number of seconds before or after the current date and time.
init(timeIntervalSince1970:) Create an NSDate instance representing a time specified by a number of seconds before or after January 1, 1970 00:00 UTC. This method exists not because Apple’s founders were California hippies nostalgic for the era of their youth, but for compatibility with Unix time.
init(timeInterval:sinceDate:) Create an NSDate instance representing a time specified by a number of seconds before or after a given NSDate.

You’ve probably noticed that none of these initializers lets you create an NSDate by giving it something convenient like a year, month, day, time zone and so on. Luckily, there are classes that will help us do this.

Creating NSDates with the help of NSCalendar and NSDateComponents

If you’re like most people, you’d probably much rather initialize a date object using a day, month, year, and time instead of some number of seconds before and after midnight on January 1, 1970, January 1, 2001, or any other arbitrary date. For this, we’ll need a couple of additional classes:

nscalendar and nsdatecomponents

First, there’s the NSCalendar class, which among other things, gives us a context for converting NSDate‘s “seconds before or after the third millennium” measurements into a familiar time system with years, months, days, hours, and minutes, and it accounts for time zones as well. Most of the time, the date and time system will be the Gregorian calendar, but iOS also lets you choose from 15 other calendar systems, including Hebrew and Buddhist.

Next, there’s the NSDateComponents class, which is an assembly of properties that make up a date, such as year, month, date, hour, minute, second, and so on. An NSDateComponents instance can be used to represent either:

  • A specific point in time, or
  • a duration of time.

To create an NSDate by specifying things like a year, month, day, and time, we’ll do the following:

  • Create an NSCalendar instance pointing to the user’s calendar
  • Specify a date using an NSDateComponents instance
  • Create the NSDate by passing the NSDateComponents instance to NSCalendar‘s dateFromComponents instance method

nsdatecomponents to nsdate

Let’s go back to our playground and create our first historical date: that of Alexander Graham Bell’s first phone call. We know it took place on March 10, 1876. While we don’t know the exact time it happened, we do know that it happened in North America’s Eastern time zone, as opposed to something like Kiritimati, a.k.a. Christmas Island. That place is 19 hours ahead and would’ve resulted in historians recording that day as March 11th rather than the 10th.

Enter or paste the highlighted code below so that your playground looks like this:

Any calendar, regardless of its time zone, to turn date components into dates using its calendar system. If you specify a time zone in the date components, it will take that time zone into account; if you don’t specify one, the date will be created using the calendar’s time zone. We created an instance of the user’s calendar, which incorporates the user’s local and time zone settings, because it’ll be useful later when we want to go in the opposite direction and convert dates into date components.

Note that after setting the year, month, and day properties of firstLandPhoneCallComponents, we set the timeZone component using the preferred initializer, init(name:), which lets you specify a time zone by any of the standard string identifiers listed in the tz database of time zones. I could’ve used one of the city names such as America/New_York (or for those of you familiar with Canada, America/Toronto, America/MontrealAmerica/Atikokan, or America/Pangnirtung) to specify the Eastern time zone. It’s far clearer — especially to people not from the U.S. — to use the time zone names that begin with US or Canada, such as US/Eastern, US/Central, US/Mountain, and US/Pacific rather than city names.

Once we’ve set up the date components, we use the calendar’s dateFromComponents instance method to convert them into a date. I’m in the US/Eastern time zone, the same one as the one specified in the date components, so the result in the sidebar beside this line of code shows as “Mar 10, 1876, 12:00 AM” (we didn’t specify a time in the date components, so the resulting date has the default time of 00:00). The date displayed in the sidebar uses your system settings, which may be different from mine.

Let’s enter the other three historic dates. Enter or paste the highlighted code below so that your playground looks like this:

Note that we used different time zones for the “Stevenotes”. Both took place at the same time, 10:00 a.m. Pacific, but we set the time for the iPhone announcement as 1:00 p.m. US/Eastern, and the time for the iPad announcement as 10:00 a.m. US/Pacific. Both results in the sidebar appear at the same time; on my machine, they appear as Jan 27, 2010, 1:00 PM.

dateFromComponents works with what you give it

Suppose we want to create a date just by specifying that it’s 11:00 a.m. on the first Saturday of March 2015 in the US/Eastern time zone. Here’s how it’s done:

NSDateComponentsweekday property lets you specify a weekday numerically. In Cocoa’s Gregorian calendar, the first day is Sunday, and is represented by the value 1. Monday is represented by 2, Tuesday is represented by 3, all the way to Saturday, which is represented by 7.

The weekdayOrdinal property lets you specify which specified weekday of the month. By setting weekday to 7, we’re specifying a Saturday; by then setting weekdayOrdinal to 1, we’re specifying the first Saturday of the month.

Here’s another example, where we get the date for the Thursday on the 18th week of 2015:

The other way around: getting NSDateComponents from NSDates

Right now, your playground should look like this, with a number of dates being created from date components:

Now it’s time to go the other way around, and extract date components from those dates. Once again, it’s the calendar that provides the method for making the conversion.

To extract NSDateComponents from an NSDate, we’ll do the following:

  • Create NSCalendar instances, if needed
  • Specify a set of date components using NSCalendarUnit bitmasks
  • Create the NSDateComponents by passing the NSDate instance to NSCalendar‘s components instance method

nsdate to nsdatecomponents

We already have a calendar instance: userCalendar, which is associated with the user’s time zone. If we use it to extract date components from a given date, the dates and times will be interpreted in the context of its time zone.

Let’s create two more calendars with two different time zones:

  • The US/Pacific time zone (UTC-08:00)
  • The Japan time zone (UTC+09:00)

Here’s what the code looks like:

Extracting all the possible date components from a date can be computationally costly, so NSCalendar‘s components instance method requires you to specify the components you want to extract. We want to extract these components from our dates:

  • year
  • month
  • day
  • hour
  • minute
  • weekday
  • weekdayOrdinal

Here’s the code that specifies this:

Now that we’ve done that, we can start extracting date components:

In your playground’s sidebar, you should see results similar to those listed in the table below:

Component My user calendar Pacific calendar Japan calendar
year 2007 2007 2007
month 1 1 1
day 9 9 10
hour 13 10 3
minute 0 0 0
weekday 3 3 4
weekdayOrdinal 2 2 2

As you can see, January 9, 2007 at 10:00 a.m. in the US/Pacific time zone is January 9, 2007 at 1:00 p.m. in my time zone (US/Eastern) and January 10, 2007 at 3:00 a.m. in Japan. In the US, that date was the second Tuesday in January 2007; in Japan, it was the second Wednesday.

Turning dates into strings (and vice versa) with NSDateFormatter

nsdate - nsdateformatter - stringJust as you use an calendar to convert date components into dates and vice versa, you use a date formatter — an instance of the NSDateFormatter — to do the conversions.

Formatting date strings for the user

If you need to display a date as text for the user, it’s best if you use Cocoa’s built-in date styles. These are a set of predefined styles for formatting dates and times based on the user’s preferred settings. These styles, which are all values of the NSDateFormatterStyle enumeration, come in a selection of lengths — short, medium, long, and full — and using them is the preferred way to create date strings for the user to read.

Add the following code to your playground:

Here’s how the various date and time formatter styles get rendered:

If dateStyle and timeStyle are both set to… the date formatter’s output looks like…
NoStyle
ShortStyle 1/27/10, 1:00 PM
MediumStyle Jan 27, 2010, 1:00:00 PM
LongStyle January 27, 2010 at 1:00:00 PM EST
FullStyle Wednesday, January 27, 2010 at 1:00:00 PM Eastern Standard Time

What’s up with NoStyle? It’s there so you can limit the resulting string so that it shows only the date or only the time.

NSDateFormatter has a timeZone property so that you can ensure that the date string reflects a specific time zone:

Formatting date strings for other computers

As I wrote earlier, if you’re formatting dates for the user, it’s strongly recommended that you use NSDateFormatter‘s dateStyle and timeStyle properties, which will format dates and times according to the user’s settings. However, if you need to need your date strings to be in a specific format (for an API, for example), you can provide NSDateFormatter with a format string:

While you can browse through Appendix F of the Unicode Technical Standard #35 to look at all the date format specifiers supported by NSDateFormatter, you might find it easier to use the table below. It shows a number of format strings applied to the iPhone announcement date (January 9, 2007 at 10:00 a.m. Pacific):

Format string Result
'Year: 'y' Month: 'M' Day: 'd Year: 2007 Month: 1 Day: 9
MM/dd/yy 01/09/07
MMM dd, yyyy Jan 09, 2007
E MMM dd, yyyy Tue Jan 09, 2007
EEEE, MMMM dd, yyyy' at 'h:mm a. Tuesday, January 09, 2007 at 10:00 AM.
EEEE, MMMM dd, yyyy' at 'h:mm a zzzz. Tuesday, January 09, 2007 at 10:00 AM Pacific Standard Time.

Turning strings into dates

If you specify a date format string, you can use NSDateFormatter to take a string following that format to turn it into an NSDate. For example:

Tying it all together

If you’ve made it to this point in the article, this chart should now make sense:

cocoa date time class chart

Once again, click the chart to see it at full size.

You should now be able to:

  • Create dates “from scratch” (that is, create them using an offset of a number of  seconds from the start of the third millennium)
  • Create dates from date components (that is, from numbers representing a day, month, and year)
  • Convert between dates and date components
  • Convert dates into string representations and string representations of dates into dates

In the next article in this series, we’ll look at date calculations and some handy functions that let you harness Swift’s expressive power and make working with dates easier.

dates and times in swift - smallRelated articles

A very brief introduction to date formatting in Swift and iOS: The oversight in a mostly-good book on Swift programming led me down the path of writing articles about dates and times in Swift, starting with this one, where I look atNSDateFormatter.

How to work with dates and times in Swift, part two: Calculations with dates: Now that we’ve got the basics, it’s time to do some date arithmetic: comparing two dates to see which one is the earlier and later one, finding out how far apart two dates are, and adding and subtracting from dates.

How to work with dates and times in Swift, part three: Making date arithmetic more Swift-like: Cocoa’s date and time classes have an Objective-C heritage, which in the Swift context, feel kind of clunky. In this article, I look at ways — and by ways, I mean helper functions and class extensions — to make date calculations feel more like Swift.

How to work with dates and times in Swift, part four: A more Swift-like way to get the time interval between two dates: This quick article shows you how to make an operator overload that makes getting the time interval between two dates more like subtraction.

Categories
Uncategorized

Pivoting is the sincerest form of flattery (or: What the Android team did when the iPhone was announced)

Photoillustration of a woman photocopying an iPhone.

Relax, Fandroids. I kid because I care.

Cover of 'Dogfight' by Fred Vogelstein.“As a consumer, I was blown away,” says Googler Chris DeSalvo in a quote from Fred Vogelstein’s book, Dogfight, upon seeing the now-legendary January 9, 2007 Stevenote when he unveiled the first iPhone.

“I wanted one immediately,” DeSalvo continues. “But as a Google engineer, I thought ‘We’re going to have to start over.’

According to the Atlantic article The Day Google Had to ‘Start Over’ on Android, an excerpt from Dogfight, Google’s big concern at the time was Microsoft. It made sense at the time: They seemed to be making the right moves. If you remember those days, Windows Mobile 5.0 was the third revision of their mobile operating system, and true to the general rule about Microsoft revs, it was finally good enough. They’d lined up an impressive array of nearly 50 hardware partners, including HTC, who’d end up shipping the most WinMo phones, and the big coup: Palm, whom they’d convinced to build phones that ran WinMo. Their OS featured mobile versions of Office. The industry rumblings were that Microsoft would end up eating away at the dominant phone OS player at the time, Symbian. “Microsoft comes out fighting when threatened,” the conventional wisdom said. “Remember what happened in the browser wars?”

Here’s what was considered to be the game-changer that would make Microsoft a serious mobile threat: the Palm Treo 700w

Palm Treo 700w phone

The Palm Treo 700w.

The best smartphones of the era followed a design template that had been defined years earlier by the Blackberry: screen at the top, physical keyboard at the bottom, augmented by some kind of device to move the cursor (first a scroll wheel, then a D-pad, and optionally, a stylus).

Then this happened:

(If you haven’t seen it before or in a while, watch it again. You can almost feel the audience’s excitement in the opening moments, as Steve teases them with hints of what he’s about to announce. You can also feel the envy when Google’s Eric Schmidt comes onstage at the 51-minute mark — remember that he was on Apple’s board then.)

From the article:

On the day Jobs announced the iPhone, the director of the Android team, Andy Rubin, was six hundred miles away in Las Vegas, on his way to a meeting with one of the myriad handset makers and carriers that descend on the city for the Consumer Electronics Show. He reacted exactly as DeSalvo predicted. Rubin was so astonished by what Jobs was unveiling that, on his way to a meeting, he had his driver pull over so that he could finish watching the webcast.

“Holy crap,” he said to one of his colleagues in the car. “I guess we’re not going to ship that phone.”

Another key quote, this time from Ethan Beard, one of Android’s early biz dev people:

“We knew that Apple was going to announce a phone. Everyone knew that. We just didn’t think it would be that good.

With the announcement of the iPhone, the Android project, whose members had been working “sixty-tp-eighty-hour weeks for fifteen months — some for more than two years” made a pivot whose effects we’re still feeling today. The BlackBerry-like phone that they’d been working on — codename “Sooner”, with a physical keyboard, no touchscreen, and a general “me-too” design — was pushed aside. They filed mobile phone-related patents galore in September 2007. The iPhone forced them to rethink the OS and phone design, and from that came a new design, codenamed “Dream”. This pivot would require them to delay their first release by a year, and the end result was the HTC Dream, released in October 2008.

HTC Dream phone, shown in landscape mode with the sliding keyboard extended.

The HTC Dream.

As you can see, the Android weren’t so sure about all of Apple’s design decisions, hence the physical keyboard and trackball. Today’s phone designs tell you how those choices by the Android team worked out.

I’ll close with an observation based on the article by John “Daring Fireball” Gruber. He may be Apple’s freelance PR guy, but he’s often right, including in this case:

Remember a few years ago, at the height of the “Android is a ripoff of the iPhone” controversy, when Android supporters claimed that the similarities were just some sort of amazing coincidence, like Newton and Leibniz discovering calculus concurrently, because Android had started life a few years before the iPhone was introduced? Good times.

I’m going to get my paws on a copy of Dogfight and read it over the holidays. Expect a review of it in the coming weeks.

 

Categories
Uncategorized

Updating RayWenderlich.com’s “AFNetworking Crash Course” for iOS 6

weather app

Whether you’re new to iOS programming or a long-timer, RayWenderlich.com is a valuable resource for the iOS developer. They regularly publish tutorials, tips, tricks and other goodies that you’d be crazy to do without if you’re serious about writing apps for iDevices. In addition to articles on the site, they go deeper with their books, which are excellent.

RayWenderlich.com recently published an article titled AFNetworking Crash Course, which covers how to write networking apps using AFNetworking, a library created by the folks at Gowalla that simplifies iOS network programming. In this tutorial, you build a weather app that uses AFNetworking to get its data from the World Weather Online service. Check it out; AFNetworking’s useful, and the tutorial’s pretty nice.

In order to reach the widest possible audience, the tutorial was written for iOS 5 and earlier versions of Xcode. If you’re developing with the current version of Xcode and for iOS 6 (which accounted for 83% of all iOS traffic in North America in February), you might want to make a few changes to the code in the tutorial. I’ve listed the changes below:

Use Modern Array Notation

Here’s the old way to get at the element of an array whose index is theIndex in Objective-C:

It’s a little clunky, and as I wrote in an earlier article, Objective-C’s New NSNumber, NSArray and NSDictionary Syntaxes Mean Less “Yak Shaving” for iOS and OS X Developers, there’s a much nicer way to do it:

In AFNetworking Crash Course, where you see code like this:

change it to this:

Use Modern Dictionary Notation

Here’s the old way to get at the item in a dictionary whose key is theKey:

Again: it’s clunky. Also again, in my earlier article, I showed the modern way to access dictionary items:

Setting items for a dictionary used to be like this:

Now, it’s like this:

So, in the places where you see code like:

change it to:

…and where you see code like:

change it to:

Update the Deprecated Location Manager Delegate Method

If you use the code as-is with iOS 6, you’ll get an error message that looks like this:

Deprecated in iOS 6.0
locationManager:didUpdateToLocation:fromLocation:
Tells the delegate that a new location value is available. (Deprecated in iOS 6.0. Use locationManager:didUpdateLocations: instead.)

Instead of using the deprecated locationManager:didUpdateToLocation:fromLocation: method, use the current locationManager:didUpdateLocations: method instead:

Categories
Uncategorized

Mobile Developer News Roundup: RubyMotion Tutorial, Android Phone-Based IDE, iOS Image Tricks and Android Design Tips

RubyMotion Tutorial

Clay Allsop’s RubyMotion Tutorial appears to be the most complete tutorial on the topic online. If you don’t relish the idea of programming in Objective-C but want to write native iPhone apps, you should check out this tutorial and see if coding apps in Ruby with RubyMotion is for you.

If you’re feeling really ambitious, you can fork the tutorial on GitHub and rewrite or expand upon your own version.

Links

AIDE: Android Java IDE

AIDE, the Android Java IDE, lets you code apps for Android devices on an Android device. It’s fully compatible with Eclipse projects, supports the full edit-compile-run cycle and has an editor with desktop IDE features like code completion, real-time error checking, refactoring and smart code navigation. According to the description, AIDE will “turn your Android tablet with keyboard into a real development box” and will “turn your Android Phone into a small development computer to browse and touch your code on the go.”

Links

iOS Image Tricks

Adam from Dwellable, the app for finding and reviewing vacation rental homes, shares some iOS image tricks that he used while taking the iPad version of the app and converting it into an iPhone app. These tricks we necessary the app, while it ran acceptably on the iPhone 4, was unacceptable slow on older units like the iPhone 3. The tricks he discusses are:

  • Using an image pipeline to serve the right image for older iPhones, retina iPhones and iPads
  • Using spriting — instead of sending a number of images, send a single large image made up of a bunch of images
  • Using 16-bit images with older devices to conserve memory

Links

Designing for Android: Tips and Techniques

Here’s a guide for designers to help them design for Android, whose ecosystem has many combinations of OS, screen size, aspect ratio and pixel density. In combination with the design guidelines on the Android Design site, this guide will help you make beautiful, usable Android apps.

Links

Categories
Uncategorized

Mobile Developer News Roundup for Tuesday, July 31st, 2012

A Mobile Privacy Policy You Can Use and Customize

Here’s a set of open source mobile privacy policies that you can copy, modify and use for your own mobile apps. Created by Docracy, an online store of open legal documents, you can use them as-is, or use them as a starting point for your app’s privacy policy. Most users consider the mobile device to be more personal than their desktops or laptops (even though they’re called personal computers), and it’s expected that privacy policies will eventually be required for apps; grab these and get a head start! Best of all, Docracy lets you fork their documents GitHub-style.

Links

ManiacDev’s Catalog of Open Source iPhone and iPad Apps

ManiacDev has updated their list of iOS apps for which the source code is available — there are now 85! 67 are currently available in the App Store, and while the remainder aren’t, they were at one time and you can still get the source for all of them. There’s nothing like learning from source code for complete, released applications, and I haven’t seen a bigger collection of such for iOS. If you’re interested in the source for games only, ManiacDev has a “just the games” list.

Links

TheNewBoston.com’s 200-Episode Android Tutorial Video Series

TheNewBoston.com has a video series made up of 200 videos covering Android development. The series starts with downloading and installing the JDK, Eclipse and the Android SDK, covers a lot of ground on writing Android apps, and ends with putting an app on the market and updating it. The presentation style is extremely casual and even made me chuckle a couple of times. I think it’s a pretty good launching point: use these videos as your launching point, back them up with the Android docs, and you’ll be on your way.

Links

Making Money in the App Store in “The Next 19%”

Dave Addey does some back-of-the-envelope calculations and says that while it’s increasingly unlikely for you to get your app in the top 1% of Apple’s App Store, you’ve got decent odds for getting your app into the sweet spot of what he calls “The Next 19%”.  He says that if the numbers he’s using are representative, the iOS App Store breaks down this way:

Tier How many apps? %age of Revenue Average income per app
Top 1% 6,500 36%, or $1.75 billion $269,230
The “Next 19%” 123,500 61%, or $3.05 billion $24,696
Bottom 80% 520,000 3%, or $150 million $288

 

He writes:

With the App Store maturing, hitting that top 1% increasingly requires sizeable investment and marketing in addition to app development skills. Successfully launching a 1% app (even with sizeable investment) isn’t something you’d bet your mortgage on, and I’d go as far as to say that this top end of the store is no longer a market that’s available to small independent developers.

The next 19%, however, is definitely a viable aspiration. Most of the paid apps we’ve released have fitted comfortably within the upper bounds of this part of the graph (beating the 19% average mentioned above), and these kinds of apps are definitely within reach of small development teams or sole developers.

Links

Categories
Uncategorized

Vaya con iOS, Entry #3: Some Personal Notes, iTunes U and The iOS Apprentice

Some Personal Notes

As I wrote earlier, I’ve declared a bit of a summer vacation for myself, but that doesn’t mean it’s been all fun and games and loafing about. I mean there’s been some fun and games and loafing about, but there’s also been a little work as well, what with lining up some conversations about work opportunities, updating the LinkedIn profile and old-school resume and of course, learning iOS development, which is what the Vaya con iOS series of articles is all about.

So, with my trusty MacBook Pro, iPad 2 and iPhone 4S, I got to work…

Just kidding — that’s not me.

As I said, with my trusty Mac and iTools, I got to work…

Okay, enough fooling around.

This is really me. I’m at the girlfriend’s place in Tampa. She goes off to work, while I start the day with an energizing swim at the central pool that almost no one in this townhouse complex seems to use:

Sixty to eighty lengths of the pool later, I emerge, shower, get dressed and then it’s time to get cracking:

She has a desk set up in her living room, which I’ve commandeered for my studies and other work. The laptop, mouse, iPad and phone are mine; Tux, the SUSE gecko, IBM bee and Sun dolphin (alas, it’s not in the shot) are hers.

A few people asked about the Nyan Cat sticker. I bought it at — I almost hate to admit this — Hot Topic (they have good pop culture stickers), cut it into two sections and laid it carefully around the trackpad.

iTunes U’s iPad and iPhone Application Development Course

There’s a pretty interesting iPad and iPhone programming course on iTunes U taught by Stanford’s Paul Hegarty. I enjoy his lectured and have watched the first three without zoning out or dozing off, which I must say is a damned sight better than some moments in my colourful academic career. I suppose not being hung over helps.

Over the course, which was recorded as it took place in the fall term of 2011, students were expected to build two complete iOS applications, with each lecture providing more material. There are 19 lectures in the series, which also includes some supplementary sessions as well as the slides for each lecture. It’s a Stanford computer science course without the Stanford tuition — it’s free! All you need is iTunes. If you decide to subscribe, be sure to get the 2011 course, as it covers iOS 5.

Ray Wenderlich and the iOS Apprentice

While researching blogs and other sites with useful information for developers with programming experience but little or no iOS development practice, I stumbled across Ray Wenderlich’s site. It’s updated regularly with new articles about various aspects of iOS development, and there’s also a regular email newsletter. One of the enticements for subscribing is that subscribers get a free tutorial — the first part of a tutorial series called The iOS Apprentice, written by Matthijs Hollemans.

I used to do Windows Phone tutorials back when I was a developer evangelist at Microsoft, and I was curious to see how someone else did it. So I signed up and soon afterwards, I got an email with the download link for the tutorial, a zip file with the tutorial in HTML form, plus XCode project files for the completed application and all the graphics and other resources needed.

I was impressed, especially because this was free. It’s on par with the NerdDinner tutorial for ASP.NET MVC, which I called the best “chapter one” I’ve ever read.

The tutorial is huge and it’s beautiful; it looks as if it was made by Apple. If you turn it into a PDF, it becomes a 117-page book, and it covers the development of a “Bull’s Eye” game, in which you try to position a slider as close as possible to a specified target value. In the process, you learn a lot: you get an intro to programming in general and XCode in particular, setting up UI controls and responding to events, dealing with different device orientations, adding a modal screen, customizing controls with your own graphics, giving your app an icon, dealing with regular and Retina displays, deploying your app to a device and more.

The tutorial was written for people who’ve never programmed before, but it does move pretty quickly. I wonder if complete novices get stuck in the process. However, I found it easy and skipped the parts in which programming concepts were explained, focusing more on the iOS-specific parts. I didn’t find the fact that it was written for beginners a bother, and I had a lot of fun in the process of following along. I even opened another project to noodle with the concepts I was learning from the tutorial.

In fact, I had so much fun with the Bull’s Eye tutorial that I decided to spend the $54 and purchase the rest. I’m currently on part 1 of the second tutorial, in which you build a reminder list app, which covers TableView-based applications. I found The iOS Apprentice more appealing and more packed with useful information than a number of iOS development books that I’d had the chance to read over and that it’s money well-spent.

If you’ve been putting off learning iOS development for whatever reason, go sign up for the newsletter at Ray Wenderlich’s site, get the first tutorial for free and give it a try. You might be pleasantly surprised.