Categories
Uncategorized

Mobile roundup: Apple’s astonishing quarter, Samsung’s upcoming quarterly report, and BlackBerry’s modest proposal

Apple’s astonishing quarter

the most profitable quarter ever
Yesterday, which also happened to be the fifth anniversary of Steve Jobs’ iPad announcement…

Apple posted the financial results for their fiscal first quarter of 2015, in which they made a net profit of $18 billion. That’s not just a record for Apple, but for any company, any time in human history. The previous record-holder was the Russian firm Gazprom, the world’s largest extractor of natural gas.

The insanely popular iPhone 6 and 6 Plus carried the company, who sold nearly 75 million iPhones (in previous quarters, they had yet to surpass the 60 million mark, never mind 70 million), a 46% increase from the same quarter in the preceding year. “Greater China” — Apple’s term for the area comprising mainland China, Hong Kong, and Taiwan — helped push Apple over the top. They accounted for $16 billion of the nearly $75 billion revenue for Q1 2015.

This success in China comes at a cost to Samsung, whose market share in the Middle Kingdom is dropping. There’s a good summary of this situation in Bloomberg Business’ article, Apple Learns What Samsung Forgot: How to Sell Phones in China.

If there’s a cloud in all this silver lining, it’s iPad sales, which dropped to 21.4 million, a decrease of 21% year over year. In Wired’s article, How the iPad Went From Massive to ‘Meh’ in 5 Short Years, it’s noted that the iPad lives in that zone between smartphone and laptop, a gap that’s being closed by larger phones and thinner, lighter laptops.

Samsung: Speaking of earnings reports…

samsung q4 2014 report
Samsung will release its 4Q 2014 earnings report on Thursday morning in Seoul (in the UTC+0900 time zone, 14 hours ahead of North America’s Eastern Time), before markets open. According to the Wall Street Journal, here’s what we should expect:

  • Net profit: 4.5 trillion won ($4.2 billion)
  • Revenue: 52 trillion won ($48.3 billion)
  • Mobile: operating profit down 65% from the same time during the previous year, shipped 10 million fewer units as well
  • Chips: a 40% rise in profit, and increased production of mobile processors for both their devices and Apple’s

BlackBerry’s modest proposal

blackberry free market
In a recent post on BlackBerry’s blog, CEO John Chen talks about net neutrality and carrier neutrality, and what he says sounds sane and sensible. He then follows with application/content neutrality, and that’s where things get a little weird:

Unlike BlackBerry, which allows iPhone users to download and use our BBM service, Apple does not allow BlackBerry or Android users to download Apple’s iMessage messaging service. Netflix, which has forcefully advocated for carrier neutrality, has discriminated against BlackBerry customers by refusing to make its streaming movie service available to them. Many other applications providers similarly offer service only to iPhone and Android users. This dynamic has created a two-tiered wireless broadband ecosystem, in which iPhone and Android users are able to access far more content and applications than customers using devices running other operating systems. These are precisely the sort of discriminatory practices that neutrality advocates have criticized at the carrier level.

Therefore, neutrality must be mandated at the application and content layer if we truly want a free, open and non-discriminatory internet. All wireless broadband customers must have the ability to access any lawful applications and content they choose, and applications/content providers must be prohibited from discriminating based on the customer’s mobile operating system.

In other words, “Developers and online services like Netflix should be mandated by law to build BlackBerry apps,” apparently forgetting that in better BlackBerry-dominated times, BBM was a BlackBerry-only service and a competitive advantage.

PC World’s Jared Newman does a great job of explaining why Chen is wrong when it comes to “app neutrality”:

On some level, Chen’s position is understandable. The point of net neutrality is to encourage innovation in online services, and to prevent Internet providers from picking winners and losers. Chen is saying that BlackBerry hasn’t been given a fair shot because app makers have declared iOS and Android victorious.

But there’s a critical difference between net neutrality and the app neutrality that Chen proposes: With net neutrality, non-discrimination is the default. The Internet stops being neutral only if Internet providers create new, discriminatory practices such as blocking, throttling and fast lanes. The point of net neutrality rules is to maintain the Internet in its non-discriminatory state.

With Chen’s proposal of app neutrality, no such non-discriminatory state exists. Each new platform merely creates more work for developers, thereby requiring greater investment. Under Chen’s proposal, the barriers to entry for a small startup would become greater, and innovation would be stifled. App neutrality may be beneficial for BlackBerry, but it would actually counteract the things that net neutrality is trying to achieve.

Our guess is that Chen added “app neutrality” to his article on net neutrality as a way to attract more attention to it, generate discussion, and keep BlackBerry on people’s minds. Well played, sir.

At least it’s not as bad as tweeting BlackBerry promotional messages from an iPhone…

this article also appears in the GSG blog

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:

// Playground - noun: a place where people can play

import UIKit

let now = NSDate()
print(now)
now.timeIntervalSinceReferenceDate

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:

// Playground - noun: a place where people can play

import UIKit

let now = NSDate()
println(now)
now.timeIntervalSinceReferenceDate

// March 10, 1876 was 3,938,698,800 seconds before the third millennium (January 1, 2001 midnight UTC)
let firstLandPhoneCallDate = NSDate(timeIntervalSinceReferenceDate: -3_938_698_800.0)

// April 3, 1973 was 875,646,000 seconds before the third millennium
let firstCellPhoneCallDate = NSDate(timeIntervalSinceReferenceDate: -875_646_000.0)

// January 9, 2007, 18:00 UTC was 190,058,400 seconds after the third millennium
let iPhoneAnnouncementDate = NSDate(timeIntervalSinceReferenceDate: 190_058_400.0)

// January 27, 2010, 18:00 UTC was 286,308,000 seconds after the third millennium
let iPadAnnouncementDate = NSDate(timeIntervalSinceReferenceDate: 286_308_000.0)

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:

// Playground - noun: a place where people can play

import UIKit

// The user's calendar incorporates the user's locale and
// time zones settings, so we'll often use it.
let userCalendar = NSCalendar.currentCalendar()


// March 10, 1876
// In this case, we're using an NSDatesComponents instance
// to represent a date rather than a duration of time.
let firstLandPhoneCallDateComponents = NSDateComponents()

// We don't know the time when Alexander Graham Bell made
// his historic phone call, so we'll simply provide the
// year, month and day. 
// We *do* know that he made that call in North America's
// eastern time zone, so we'll specify that.
firstLandPhoneCallDateComponents.year = 1876
firstLandPhoneCallDateComponents.month = 3
firstLandPhoneCallDateComponents.day = 10
firstLandPhoneCallDateComponents.timeZone = NSTimeZone(name: "US/Eastern")

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:

// Playground - noun: a place where people can play

import UIKit

// The user's calendar incorporates the user's locale and
// time zones settings, so we'll often use it.
let userCalendar = NSCalendar.currentCalendar()


// March 10, 1876
// In this case, we're using an NSDatesComponents instance
// to represent a date rather than a duration of time.
let firstLandPhoneCallDateComponents = NSDateComponents()

// We don't know the time when Alexander Graham Bell made
// his historic phone call, so we'll simply provide the
// year, month and day. 
// We *do* know that he made that call in North America's
// eastern time zone, so we'll specify that.
firstLandPhoneCallDateComponents.year = 1876
firstLandPhoneCallDateComponents.month = 3
firstLandPhoneCallDateComponents.day = 10
firstLandPhoneCallDateComponents.timeZone = NSTimeZone(name: "US/Eastern")

// We have a calendar and date components. We can now make a date!
// On my system (US/Eastern time zone), the result for the line below is
// "Mar 10, 1876, 12:00 AM"
let firstLandPhoneCallDate = userCalendar.dateFromComponents(firstLandPhoneCallDateComponents)!


// April 3, 1973
let firstCellularPhoneCallDateComponents = NSDateComponents()
firstCellularPhoneCallDateComponents.year = 1973
firstCellularPhoneCallDateComponents.month = 4
firstCellularPhoneCallDateComponents.day = 3
firstCellularPhoneCallDateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Apr 3, 1973, 12:00 AM"
let firstCellularPhoneCallDate = userCalendar.dateFromComponents(firstCellularPhoneCallDateComponents)!


// January 9, 2007, 18:00 UTC
let iPhoneAnnouncementDateComponents = NSDateComponents()
// We know that the "Stevenote" when the iPhone was announced
// started at 10:00 am Pacific time.
iPhoneAnnouncementDateComponents.year = 2007
iPhoneAnnouncementDateComponents.month = 1
iPhoneAnnouncementDateComponents.day = 9
iPhoneAnnouncementDateComponents.hour = 13
iPhoneAnnouncementDateComponents.minute = 0
iPhoneAnnouncementDateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Jan 9, 2007, 1:00 PM"
let iPhoneAnnouncementDate = userCalendar.dateFromComponents(iPhoneAnnouncementDateComponents)!


// January 27, 2010, 18:00 UTC
// We know that the "Stevenote" when the iPad was announced
// started at 10:00 am Pacific time.
let iPadAnnouncementDateComponents = NSDateComponents()
iPadAnnouncementDateComponents.year = 2010
iPadAnnouncementDateComponents.month = 1
iPadAnnouncementDateComponents.day = 27
// Let's set the clock using Pacific Time
iPadAnnouncementDateComponents.hour = 10
iPadAnnouncementDateComponents.minute = 0
iPadAnnouncementDateComponents.timeZone = NSTimeZone(name: "US/Pacific")
// On my system (US/Eastern time zone), the result for the line below is
// "Jan 27, 2010, 1:00 PM"
let iPadAnnouncementDate = userCalendar.dateFromComponents(iPadAnnouncementDateComponents)!

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:

// (Previous code goes here)

// First Saturday of March 2015, US/Eastern
let firstSaturdayMarch2015DateComponents = NSDateComponents()
firstSaturdayMarch2015DateComponents.year = 2015
firstSaturdayMarch2015DateComponents.month = 3
firstSaturdayMarch2015DateComponents.weekday = 7
firstSaturdayMarch2015DateComponents.weekdayOrdinal = 1
firstSaturdayMarch2015DateComponents.hour = 11
firstSaturdayMarch2015DateComponents.minute = 0
firstSaturdayMarch2015DateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Mar 7, 2015, 11:00 AM"
let firstSaturdayMarch2015Date = userCalendar.dateFromComponents(firstSaturdayMarch2015DateComponents)!

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:

// (Previous code, including the definition of calendar,
// goes here)

// Thursday of the 18th week of 2015, US/Eastern
let thursday18thWeekOf2015DateComponents = NSDateComponents()
thursday18thWeekOf2015DateComponents.year = 2015
thursday18thWeekOf2015DateComponents.weekOfYear = 18
thursday18thWeekOf2015DateComponents.weekday = 5
thursday18thWeekOf2015DateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// ""Apr 30, 2015, 12:00 AM""
let thursday18thWeekOf2015Date = userCalendar.dateFromComponents(thursday18thWeekOf2015DateComponents)!

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:

// Playground - noun: a place where people can play

import UIKit

// The user's calendar incorporates the user's locale and
// time zones settings, so we'll often use it.
let userCalendar = NSCalendar.currentCalendar()


// March 10, 1876
// In this case, we're using an NSDatesComponents instance
// to represent a date rather than a duration of time.
let firstLandPhoneCallDateComponents = NSDateComponents()

// We don't know the time when Alexander Graham Bell made
// his historic phone call, so we'll simply provide the
// year, month and day. 
// We *do* know that he made that call in North America's
// eastern time zone, so we'll specify that.
firstLandPhoneCallDateComponents.year = 1876
firstLandPhoneCallDateComponents.month = 3
firstLandPhoneCallDateComponents.day = 10
firstLandPhoneCallDateComponents.timeZone = NSTimeZone(name: "US/Eastern")

// We have a calendar and date components. We can now make a date!
// On my system (US/Eastern time zone), the result for the line below is
// "Mar 10, 1876, 12:00 AM"
let firstLandPhoneCallDate = userCalendar.dateFromComponents(firstLandPhoneCallDateComponents)!


// April 3, 1973
let firstCellularPhoneCallDateComponents = NSDateComponents()
firstCellularPhoneCallDateComponents.year = 1973
firstCellularPhoneCallDateComponents.month = 4
firstCellularPhoneCallDateComponents.day = 3
firstCellularPhoneCallDateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Apr 3, 1973, 12:00 AM"
let firstCellularPhoneCallDate = userCalendar.dateFromComponents(firstCellularPhoneCallDateComponents)!


// January 9, 2007, 18:00 UTC
let iPhoneAnnouncementDateComponents = NSDateComponents()
// We know that the "Stevenote" when the iPhone was announced
// started at 10:00 am Pacific time.
iPhoneAnnouncementDateComponents.year = 2007
iPhoneAnnouncementDateComponents.month = 1
iPhoneAnnouncementDateComponents.day = 9
iPhoneAnnouncementDateComponents.hour = 13
iPhoneAnnouncementDateComponents.minute = 0
iPhoneAnnouncementDateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Jan 9, 2007, 1:00 PM"
let iPhoneAnnouncementDate = userCalendar.dateFromComponents(iPhoneAnnouncementDateComponents)!


// January 27, 2010, 18:00 UTC
// We know that the "Stevenote" when the iPad was announced
// started at 10:00 am Pacific time.
let iPadAnnouncementDateComponents = NSDateComponents()
iPadAnnouncementDateComponents.year = 2010
iPadAnnouncementDateComponents.month = 1
iPadAnnouncementDateComponents.day = 27
// Let's set the clock using Pacific Time
iPadAnnouncementDateComponents.hour = 10
iPadAnnouncementDateComponents.minute = 0
iPadAnnouncementDateComponents.timeZone = NSTimeZone(name: "US/Pacific")
// On my system (US/Eastern time zone), the result for the line below is
// "Jan 27, 2010, 1:00 PM"
let iPadAnnouncementDate = userCalendar.dateFromComponents(iPadAnnouncementDateComponents)!


// First Saturday of March 2015, US/Eastern
let firstSaturdayMarch2015DateComponents = NSDateComponents()
firstSaturdayMarch2015DateComponents.year = 2015
firstSaturdayMarch2015DateComponents.month = 3
firstSaturdayMarch2015DateComponents.weekday = 7
firstSaturdayMarch2015DateComponents.weekdayOrdinal = 1
firstSaturdayMarch2015DateComponents.hour = 11
firstSaturdayMarch2015DateComponents.minute = 0
firstSaturdayMarch2015DateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Mar 7, 2015, 11:00 AM"
let firstSaturdayMarch2015Date = userCalendar.dateFromComponents(firstSaturdayMarch2015DateComponents)!


// Thursday of the 18th week of 2015, US/Eastern
let thursday18thWeekOf2015DateComponents = NSDateComponents()
thursday18thWeekOf2015DateComponents.year = 2015
thursday18thWeekOf2015DateComponents.weekOfYear = 18
thursday18thWeekOf2015DateComponents.weekday = 5
thursday18thWeekOf2015DateComponents.timeZone = NSTimeZone(name: "US/Eastern")
// On my system (US/Eastern time zone), the result for the line below is
// "Apr 30, 2015, 12:00 AM"
let thursday18thWeekOf2015Date = userCalendar.dateFromComponents(thursday18thWeekOf2015DateComponents)!

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:

// (Previous code goes here)

let pacificCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
pacificCalendar.timeZone = NSTimeZone(name: "US/Pacific")!

let japanCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
japanCalendar.timeZone = NSTimeZone(name: "Asia/Tokyo")!

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:

// (Previous code goes here)

let requestedDateComponents: NSCalendarUnit = [.Year,
                                               .Month,
                                               .Day,
                                               .Hour,
                                               .Minute,
                                               .Weekday,
                                               .WeekdayOrdinal]

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

// (Previous code goes here)

// Date components in the user's time zone
let jan9_2007Components = userCalendar.components(requestedDateComponents,
                                                  fromDate: iPhoneAnnouncementDate)
jan9_2007Components.year
jan9_2007Components.month
jan9_2007Components.day
jan9_2007Components.hour
jan9_2007Components.minute
jan9_2007Components.weekday
jan9_2007Components.weekdayOrdinal

// Date components in the US/Pacific time zone
let march10_1876PacificComponents = pacificCalendar.components(requestedDateComponents,
                                                               fromDate: iPhoneAnnouncementDate)
march10_1876PacificComponents.year
march10_1876PacificComponents.month
march10_1876PacificComponents.day
march10_1876PacificComponents.hour
march10_1876PacificComponents.minute
march10_1876PacificComponents.weekday
march10_1876PacificComponents.weekdayOrdinal

// Date components in Japan's time zone
let march10_1876JapanComponents = japanCalendar.components(requestedDateComponents,
                                                           fromDate: iPhoneAnnouncementDate)
march10_1876JapanComponents.year
march10_1876JapanComponents.month
march10_1876JapanComponents.day
march10_1876JapanComponents.hour
march10_1876JapanComponents.minute
march10_1876JapanComponents.weekday
march10_1876JapanComponents.weekdayOrdinal

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:

// (Previous code goes here)

let formatter = NSDateFormatter()

// No date style or time style defined:
// The result for the line below is
// ""
formatter.stringFromDate(firstLandPhoneCallDate)

// Only the date style is defined:
formatter.dateStyle = .MediumStyle
// The result for the line below is
// "Mar 10, 1876"
formatter.stringFromDate(firstLandPhoneCallDate)

// The date style and time style have been defined:
formatter.timeStyle = .ShortStyle
// The result for the line below is
// "Mar 10, 1876, 12:00 AM"
formatter.stringFromDate(firstLandPhoneCallDate)

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:

// (Previous code goes here)

formatter.dateStyle = .MediumStyle
formatter.timeStyle = .ShortStyle
formatter.timeZone = NSTimeZone(name: "US/Pacific")

// The result for the line below is
// "Jan 27, 2010, 10:00 AM"
formatter.stringFromDate(iPadAnnouncementDate)

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:

// (Previous code goes here)

// Setting the locale to POSIX ensures that
// the user's locale won't be used
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")

// NSDateFormatter's format string uses the date format specifiers
// spelled out in Unicode Technical Standard #35 (located at
// http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns)
formatter.dateFormat = "y-MM-dd"

// The result for the line below is
// "2007-01-09"
formatter.stringFromDate(iPhoneAnnouncementDate)

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:

// (Previous code goes here)

formatter.dateFormat = "yyyy/MM/dd hh:mm Z"
// This string will be converted to a date because
// it's in the same format as the dateFormat string:
formatter.dateFromString("2015/03/07 11:00 -0500")!
// This string will NOT be converted to a date because
// it's NOT in the same format as the dateFormat string;
// its result will be nil:
formatter.dateFromString("Mar 7, 2015 11:00 AM EST")

// Let's change the date format strings and try
// dateFromString with the same two strings:
formatter.dateFormat = "MMM d, yyyy hh:mm a zz"
// This results in an NSDate:
formatter.dateFromString("Mar 7, 2015 11:00 AM EST")!
// This results in nil:
formatter.dateFromString("2014/11/05")

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

Jimmy Kimmel asks people on the street for their passwords; security hilarity ensues

If someone walked up to you on the street and asked you what your password was, would you say?

The TV show Jimmy Kimmel Live sent an interviewer out on the street to ask (presumably) random people on Hollywood Boulevard what their passwords were. As you might expect, they showed only those people who gave away their passwords (and of that group, only those who signed a release form to appear on the show), but the fact that anyone did so shows that we’ve got a big security problem, and it’s us. A couple of them simply gave them away without question, while a couple of others has to be conned — very easily — into divulging.

This is the technologist’s nightmare. For all the security measures we put into our applications and devices, they can easily be undone by the users. That’s why I often make use of this cartoon when talking about security:

and in this corner we have dave

The article also appears in my personal blog, The Adventures of Accordion Guy in the 21st Century.

Categories
Uncategorized

SWIFTly rising up the programming language charts

swift on redmonk

Click the graph to see it at full size.

For a programming language that came out in beta in June, Swift’s rise in popularity is quite impressive. Stephen O’Grady writes in his report on Redmonk’s Programming Languages Rankings for Q1 2015, while most of the rankings stayed stable, Swift’s meteoric rise from 68th place in Q3 2014 to its present number 22 spot stands out.

As with any programming language popularity ranking system, Redmonk’s rankings are determined by looking at the online “trail” left by programming language users. Their system uses two key metrics:

  • Discussion of the language on Stack Overflow, where discussions are tagged with language names, and
  • Projects posted on GitHub, where projects are tagged with language names.

O’Grady writes:

During our last rankings, Swift was listed as the language to watch – an obvious choice given its status as the Apple-anointed successor to the #10 language on our list, Objective-C. Being officially sanctioned as the future standard for iOS applications everywhere was obviously going to lead to growth. As was said during the Q3 rankings which marked its debut, “Swift is a language that is going to be a lot more popular, and very soon.” Even so, the growth that Swift experienced is essentially unprecedented in the history of these rankings. When we see dramatic growth from a language it typically has jumped somewhere between 5 and 10 spots, and the closer the language gets to the Top 20 or within it, the more difficult growth is to come by. And yet Swift has gone from our 68th ranked language during Q3 to number 22 this quarter, a jump of 46 spots. From its position far down on the board, Swift now finds itself one spot behind Coffeescript and just ahead of Lua. As the plot suggests, Swift’s growth is more obvious on StackOverflow than GitHub, where the most active Swift repositories are either educational or infrastructure in nature, but even so the growth has been remarkable. Given this dramatic ascension, it seems reasonable to expect that the Q3 rankings this year will see Swift as a Top 20 language.

The other well-known ranking of programming language popularity, the TIOBE Index, puts Swift at the number 25 position in its January 2015 edition. They just named JavaScript as the 2014 language of the year, but as they observed:

It was a close finish. Swift and R appeared to be the main candidates for the title but due to a deep fall of Objective-C this month, a lot of other languages took advantage of this and surpassed these two candidates at the last moment.

Another interesting way to gauge a programming language’s popularity is to count the Swift courses and the number of students on Udemy. As of this writing, there are 53 Swift courses in English, and another 18 in other languages. Three of these courses have 10,000 students or more, the most popular of which is Rob Percival’s The Complete iOS and Swift Course: Learn by Building 15 Real-World Apps. It has over 53,000 students, who’ve paid as much as $199 (that’s the standard price, but there are often sales where you can sign up for much, much less).

If you’re the sort to try to read the tea leaves of programming language popularity to see what the Really Big Deals this year will be, keep an eye on what I’m calling the “Three M’s”: mobile, modelling data, and massive data. The TIOBE folks seem to agree with this assessment:

It is always tempting to try to forecast what will change in 2015. Objective-C will probably lose its dominant position in mobile app development, whereas Java and Swift will gain traction in that field. Java might even become number one of the TIOBE index again. Other trends in progamming are modelling and big data. Here, MATLAB and R appear to be the market leaders. There is a realistic chance that they will enter the top 10 in 2015.

Categories
Uncategorized

A very brief introduction to date formatting in Swift and iOS

The book 'Beginning iPhone Development with Swift'As I wrote in an earlier article, I’ve been working my way through Apress’ Beginning iPhone Development with Swiftan iOS 8/Swift-flavored update of Beginning iOS 7 Development. The original book was released in March 2014, the iOS 8 and Swift betas came out that June, the GM versions came out in September, and the revised book was released in mid-November. In the eight-month span between the original book and the revision, the authors didn’t have much time to try out iOS 8 and Swift, never mind do the rewrite, and as a result, they ended up with a few errors in their text, as well as leaving out some useful material.

I also wrote in that earlier article that in spite of these problems, I still think it’s a good book (as do some other people; it’s got 5 stars on Amazon as of this writing), and where some may see errors and oversights, I see opportunities.

Here’s another opportunity that came up…

The date picker exercise

Chapter 7 of Beginning iPhone Development with Swift, Tab Bars and Pickers, has you build a multi-view app where you use all kinds of “picker” controls. The first view you work on is one with a date picker; here’s a screen shot:

iOS app showing a date picker and a button labelled 'Select'. The selected date in the date picker is 'Today, 4:20 PM'

In this simple view, you use the picker to select a date, tap the Select button, and you’re presented with an alert that looks like this:

iOS app with date picker and button, overlaid with an alert showing the selected date as '2015-01-14 21:20:13 +0000'

Note the format of the date displayed in the alert:

  • It’s not formatted in the most readable way.
  • It has too high a level of detail. The user didn’t enter the number of seconds or a time offset.
  • I entered the time in my time zone (4:20 p.m., Eastern Standard Time, or GMT-5), but the alert is displaying the time for GMT.

Here’s what the book had to say about this:

Note
The date picker does not allow you to specify seconds or a time zone. The alert displays the time with seconds and in Greenwich Mean Time (GMT). We could have added some code to simplify the string displayed in the alert, but isn’t this chapter long enough already? If you’re interested in customizing the formatting of the date, take a look at the NSDateFormatter class.

I’d much rather have the alert look like this…

iOS app with date picker and button, overlaid with an alert showing the selected date as 'Wednesday, January 14, 2015 at 4:20 PM'

…but they’d left doing so as an exercise for the reader. Let’s go through this exercise, shall we?

The original code

Here’s what the view looks like in the Storyboard:

datepicker view

And here’s the code for buttonPressed in the corresponding view controller:

@IBAction func buttonPressed(sender: AnyObject) {
  let date = datePicker.date
  let message = "The date and time selected: \(date)"
  let alert = UIAlertController(
    title: "Date and time selected",
    message: message,
    preferredStyle: .Alert)
  let action = UIAlertAction(
    title: "That's so true!",
    style: .Default,
    handler: nil)
  
  alert.addAction(action)
  presentViewController(alert, animated: true, completion: nil)
}

In this code, we’re simply taking the value from the date picker’s date property and using its string representation in the string constant message. In iOS, dates are represented by instances of the NSDate class, which is all about representing a single point in time. While it has the date property for access the date stored within, it doesn’t have any members for formatting that date.

Enter NSDateFormatter

iOS has a number of formatter classes, whose job is to take data and convert it into a text representation, typically for the benefit of the user. These classes have names that end with the word Formatter and are subclasses of the abstract class NSFormatter. You can find out more about these classes in NSHipster’s excellent overview.

The book pointed us towards NSDateFormatter, a class that serves two purposes:

  • Converting NSDate objects into string representations, and
  • Converting strings into NSDate objects.

NSDateFormatter has a class method called localizedStringFromDate that does what we want. Given the following:

  • An NSDate instance,
  • A style specifying how we want the date part of the NSDate instance formatted, and
  • A style specifying how we want the time part of the NSDate instance formatted

…it returns a string representing the NSDate instance in the format we specified.

We specify the styles for the date and time using values from the NSDateFormatterStyle enum, which has the following values:

  • NoStyle: Unstyled.
  • ShortStyle: Typically numeric-only, such as 1/14/15 and 4:20 PM.
  • MediumStyle: A medium-length style, using abbreviations. Examples are Jan 14, 2015 and 4:20:00 PM.
  • LongStyle: A longer style with full text. Examples are January 14, 2015 and 4:20:00 PM EST.
  • FullStyle: Full style with complete details. Examples are Wednesday, January 14, 2015 and 4:20:00 PM Eastern Standard Time.

For our code, we’ll use FullStyle for the date and ShortStyle for the time. Here’s what the revised code looks like — the highlighted lines show the new or modified code:

@IBAction func buttonPressed(sender: AnyObject) {
  let date = datePicker.date
  let formattedDate = NSDateFormatter.localizedStringFromDate(
    date,
    dateStyle: .FullStyle,
    timeStyle: .ShortStyle)
  let message = "The date and time selected: \(formattedDate)"
  let alert = UIAlertController(
    title: "Date and time selected",
    message: message,
    preferredStyle: .Alert)
  let action = UIAlertAction(
    title: "That's so true!",
    style: .Default,
    handler: nil)
  
  alert.addAction(action)
  presentViewController(alert, animated: true, completion: nil)
}

This code gives us the date in a more user-friendly format.

This example scratches the surface of what’s possible with NSDateFormatter. You should take a look at Date Formatters, which is part of a larger section of their documentation called Data Formatting Guide.

dates and times in swift - smallRelated articles

How to work with dates and times in Swift, part one: An introduction of Cocoa’s date and time classes, and how they work together. This article covers UTC (Coordinated Universal Time), and the key classes: NSDate, NSCalendar, NSDateComponents.

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.

You might also want to check out: How to program an iOS text field that takes only numeric input with a maximum length

Categories
Uncategorized

Mobile pundit Tomi Ahonen’s predictions for smartphone vendors in 2015

tomi ahonen - mobile pundit

Tomi Ahonen, Nokia executive during its heyday, mobile consultant to Fortune 500 companies, prolific author, and all-round mobile curmudgeon, has published his predictions for the mobile handset industry in 2015 on his blog, Communities Dominate Brands. The title of his article, So the Smartphone ‘Bloodbath’ Annual Preview for Year 2015 – This is so boring, gives you a taste of his writing style: a little hyperbole, and a lot of stream of consciousness. It’s a big, monolithic block of text, chock-a-block with the asides that are his stock in trade, and it’s a lot to wade through.

We’ve taken Ahonen’s article and distilled it for what we think are the big take-aways from his 2015 predictions. As always, this sort of future-telling should always be taken with a grain of salt — while he often has brilliant insights into mobile tech (it’s why we read what he has to say), he’s been known to be oh-so-very-wrong from time to time (as everyone is).

Samsung

Samsung’s sitting pretty as the world’s largest handset maker, at almost twice the size of the next runner-up, and larger than the 2nd- and 3rd-place vendors combined. They’re also the largest of the “major handset makers who genuinely cater to the global mass market” (as opposed to Apple, who are aimed at the higher-end customer, or BlackBerry, whose focus is the enterprise). Their “everywhere” status means that they’ll make good money and stable, but it also means that investors can’t count on them to be as “ridiculously profitable” as Apple.

samsung galaxy k zoom

Samsung’s weakness, according to Ahonen, is their sales management, which he describes as “a total disaster”. They produce a confusing array of all-too-similar models, and fail to highlight interesting and innovative devices like the Galaxy K Zoom, which reimagines the smartphone as a camera with a great lens and 10x optical zoom that just happens to have a phone rather than the other way around, priced 20% below the latest iPhone model. Given that:

  • most people’s phones are their cameras these days,
  • we can’t post enough photos on Facebook, Twitter, Instagram, and SnapChat, and
  • camera quality is a big factor in many people’s smartphone choices,

you’d think that this would be a heavily-marketed, big-selling Android phone. But just try to find it at your local store.

samsung tizen

Tizen, Samsung’s troubled, oftendelayed device operating system that they they hope will free them from dependency on Google and Android, is expected to debut at this year’s CES, where it’ll debut on its TV sets. While the Tizen Alliance — a rag-tag group of a dozen hardware manufacturers who’ve promised to release Tizen-powered devices — seens to have fizzled out, Ahonen still believes that Samsung’s market size and clout, combined with the sort of effort and execution Samsung can make when they’re doing things right, mean that Tizen could be a game-changer over the next couple of years.

Apple

apple and ios

Apple has historically been one of Ahonen’s blind spots. Back when Nokia, Motorola, RIM, and Palm were the ones to beat, he consistently downplayed Apple. Later, as Nokia was going down in flames, his thesis was that the iPhone didn’t kill Nokia, Nokia’s response to the iPhone did.

apple watch

Ahonen’s prediction that we should start to see the final transformation of Apple into a niche OS and out of the mass market as Android assumes the position for mobile devices that Windows had for desktop computers. As for the Apple Watch, he says that yes, the iFaithful will line up to buy it, but in the end, even they will reject it in the long run.

Lenovo

lenovo

They did well for themselves in the laptop world by buying an internationally-recognized and respected brand — IBM’s ThinkPad — and turning it into a profitable business. It appears that they’re trying to repeat history now that they own the Motorola marque. Buying these brands are smart moves, says Ahonen, allowing them to sidestep the reputation of “cheap Chinese” that other vendors like Huawei and ZTE have to contend with, especially given the rave reviews their most recent phones have received. Moto, and not Xiaomi, is the biggest threat to Samsung, according to Ahonen.

Google

google

Here’s the Ahonen take in a single sentence: They won, and the only way they can lose is if they themselves screw it up.

The “Next Five” (Coolpad, Huawei, TCL, Xiaomi, ZTE)

the next five

Here in the U.S., none of these brands — Coolpad, Huawei (“WAH-way”), TCL, Xiaome (“SHOW-mee”, the first syllable rhymes with “cow”), and ZTE — are household names, but in Ahonen’s list, they’re the next runners-up after the top three smartphone vendors (Xiaomi recently moved up to the number 3 position). Xiaomi is getting a lot of press right now, partly because of its dramatic growth, and partly because they’re hardcore Apple copycats.

If he had to bet on members of the “next five”, Ahonen would put his money on Huawei and ZTE, because selling phones requires more than product, but also relationships with carriers worldwide. Huawei and ZTE have been selling telecom equipment to the carriers for years, so they have an “in” that upstarts like Xiaomi don’t.

Legacy brands (such as HTC, LG, and Sony)

legacy

Ahonen doesn’t see these vendors — HTC, LG, and Sony — making much of a mark. He says that while they may see the occasional quarter where they see “record profits” (or have moments in the sun, as LG seems to be having with well-reviewed phones like their G3), these will be fleeting moments followed by “obsolescent models are overflowing in the showrooms then there are returns to the factory and suddenly huge losses generated”. “The brand and sales channel,” he argues, “is of far more value to one of the rising stars (mostly from China) who want to take over the world than to a legacy manufacturer who suddenly sees big losses.”

BlackBerry

blackberry

“One of the saddest stories in tech,” says Ahonen. He says that the Passport and Classic missed the mark, and that while they may find a home catering to the enterprise, either as a hardware vendor or as a pure software play, they’ll never return back to the top 10. They’re even slipping out of the top 20 right now.

Microsoft (the company formerly known as Nokia)

lumia

Just as he has a bit of a blind spot for Apple, Ahonen has a sore spot about Windows Phone. He can’t talk about it without seething with rage, and especially at the Microsoft exec-turned Nokia CEO-turned Microsoft exec Stephen Elop. We’ll condense his four paragraphs on this topic to:

  • They’re soooo dead. We still have no idea why 1/3 of Lumia phones haven’t been activated!
  • Microsoft can’t kill off their smartphone business now. The best thing they can do is fire the current Windows Phone executive VP of Devices and Services (Elop) and let some hapless, well-intentioned patsy run it into the ground.
  • Expect them to ditch the phone hardware division sometime in the next three years.

The other mobile OSs

firefox sailfish ubuntu

The short version: They don’t stand a chance.

The Company still known as Nokia

real nokia

Microsoft may have bought Nokia’s handset business, but they didn’t buy the entire company. There’s still a company called Nokia that makes networking equipment for carriers, mobile mapping and navigation technologies, and even mobile devices. Right now, they’re contractually forbidden from making smartphones under their own brand for another year or so, but they’ve put out a well-reviewed tablet. Ahonen believes that with their relationships with carriers and the right execution, Nokia could make an Android-powered comeback. As a bonus, he follows this with a (long, so very, very long) “Hollywood scenario” in which Nokia’s ability to turn dying businesses around (as they did with Siemens’ telecom and Motorola’s networking divisions) and the brand loyalty they’ve earned worldwide make it surpass Apple and become Samsung’s biggest rival. It reads like fan fiction, and even he admits that it’s a very unlikely scenario.

this article also appears in the GSG blog

Categories
Swift Kick

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

Update (April 27, 2015)

updated article

Guess what — this article’s out of date. If you want the latest version of the code for programming constrained text fields in iOS with improved features, point your browser at the revised article, How to program an iOS text field that takes only numeric input or specific characters with a maximum length. It even comes with a sample app that you can download!

The original article

control fun app

One of my favorite ways to get a deeper understanding of programming in a given language or for a given platform is to pick up a highly-rated book for that language or platform and go through all the example tutorials and exercises, no matter how simple they seem. Although I often end up covering ground that I’ve gone over so many times before, I usually find that one or both of the following happen:

  • I end up learning something I didn’t know before, even in subject areas where I consider myself well-versed, or
  • I decide to see if I can improve the implementation or add a new feature, and in the process, learn about a feature new to me or figure out a new way to use a feature I’m already familiar with.

beginning ios development with swiftI got Apress’ Beginning iPhone Development with Swift for less than half price during their recent Cyber Monday sale, and I’ve been working through its tutorials during the holiday downtime. It’s a revision of a book released in late March 2014, Beginning iOS 7 Development (which I also own), updated to cover both a language and OS version whose first betas were released in June and whose 1.0 versions were made available in September. Given that the book was released in mid-November, they updated it in a hurry, which means that the book contains a few errors and oversights. In spite of this, I still recommend the book because:

  • The book is pretty much a straight “port” of an excellent book, Beginning iOS7 Development, for Swift and iOS 8, and
  • where some may see only errors and oversights, I also see learning opportunities.

The oversight

In chapter 4 of Beginning iPhone Development with Swift, whose title is More User Interface Fun, the exercise is to build an app that features a number of commonly-used user interface controls. The app you build starts with a couple of labels and text fields laid out so that they look like this:

name and number text fields

The user is supposed to be able to type in any kind of character into the Name text field, and only numeric characters into the Number field. The exercise in the chapter walks you through the process of setting the Keyboard Type of the Number field to Number Pad using the Storyboard and the Attributes Inspector:

setting keyboard type

While doing this goes a long way to preventing non-numeric input, it isn’t enough. On the iPhone, the Number Pad keyboard allows only digits to be entered…

ios 8 iphone number pad

…which works just fine if the user needs to enter positive whole numbers. If you want the user to enter negative numbers or use a decimal point, you’ll need to use the Numbers and Punctation keyboard, which features some additional characters. Here’s what it looks like on the iPhone:

ios 8 iphone numbes-punctuation keyboard

On the iPad, choosing either the Number Pad or Numbers and Punctuation keyboard gives you the same thing. It looks like this:

ipad number pad keyboard

These keyboards make it possible to enter some decidedly non-numeric input into the Number field.

copy and paste

If that weren’t enough, there’s also cut/copy and paste to contend with. The user can easily type an alphabetical string into the Name field, copy or cut it, and then paste it into the Number field. Clearly, you need to take more active measures if you want to ensure that a field meant for numeric input gets only numeric input.

Beginning iPhone Development with Swift points the way to a solution, but stops short. Here’s what the book says on page 110:

Tip    If you really want to stop the user typing anything other than numbers into a text field, you can do so by creating a class that implements the textView(_, shouldChangeTextInRange:, replacementText:) method of the UITextViewDelegate protocol and making it the text view’s delegate. The details are not too complex, but beyond the scope of this book.

This is wrong for two reasons:

  • I don’t think that disallowing unwanted characters from being input into a text field, which I think is a pretty basic UI feature in this day and age, is beyond the scope of the book, and
  • the method that should be used is part of the UITextFieldDelegate protocol, not the UITextViewDelegate protocol. As I said earlier, they rushed the production of this book.

In this article, I’m going to correct this oversight and show you how to do the following in iOS 8 and Swift:

  • Intercept the user’s input as s/he types or pastes into a text field
  • Allow only a specified set of characters to be entered into a given text field
  • Limit the number of characters that can be entered into a given text field
  • Confirm that the value entered into a text field is numeric

Intercepting the user’s input as s/he types or pastes into a text field

interception

Creative Commons photo by Torsten Bolten, AFpix.de. Click the photo to see the source.

Beginning iPhone Development with Swift was right: the way to really control what the user can enter into a text field is to implement this method in the UITextFieldDelegate protocol:

func textField(textField: UITextField, 
               shouldChangeCharactersInRange range: NSRange, 
               replacementString string: String) 
     -> Bool {
  // code goes here
}

This method, called textField(_:shouldChangeCharactersInRange:replacementString:), is automatically called in view controllers that conform to the UITextFieldDelegate protocol whenever the user adds a new character to a text field or deletes an existing one. It gives you three parameters to work with:

  • textField: The text field whose contents are being changed
  • range: The range of characters to be replaced
  • string: The replacement string

If we want to accept the changes that the user made to the text field as-is, we have this method return true. If we don’t want to accept the changes, or if we want to alter them, we have this method return false.

In order to implement this method, we need to make the view controller conform to the UITextFieldDelegate protocol. We do this by adding UITextFieldDelegate the view controller’s declaration. In this example, the view controller is simply named ViewController, so we’ll added UITextFieldDelegate to its declaration like so:

class ViewController: UIViewController, UITextFieldDelegate {

  // The rest of the class' code goes here

}

In this example, the text field that we want to make “numbers only” is named numberField. We need to specify its delegate — the class containing the UITextFieldDelegate protocol methods that will be called whenever changes are made to its contents. We’ll specify that the view controller should be the delegate, and we’ll do it in the viewDidLoad() method:

override func viewDidLoad() {
  super.viewDidLoad()
    
  numberField.delegate = self
}

Allowing only a specified set of characters to be entered into a given text field

Now that we have the view controller properly set up as a delegate for calls from the numberField text field whenever changes are made to its content, it’s time to implement textField(_:shouldChangeCharactersInRange:replacementString:). We want to implement it in such a way that the only characters that can be entered or pasted into numberField are the digits 0 through 9 and the . and characters.

Here’s the code:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
  var result = true
  
  if textField == numberField {
    if count(string) > 0 {
      let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet
      let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
      result = replacementStringIsLegal
    }
  }

  return result
}

The method starts off with the assumption that the user’s input is legal, and then applies the test to see if that’s actually the case. It then checks to see that the text field whose contents changed is numberField, the field whose content we want to restrict to numeric values. Next, it sees if the replacement string contains at least one character; if it doesn’t, there’s no point testing its content.

The method makes use of an NSCharacterSet instance to define the set of characters that we don’t want to allow inside numberField. Since the set of disallowed characters is much larger than the set of characters we want to allow in numberField,  we define the set by first creating an NSCharacterSet of allowed characters and use the invertedSet method.

Once we’ve defined a set of disallowed characters, we test the replacement string string to see if it contains any of them. If the replacement string string contains disallowed characters, string.rangeOfCharactersFromSet(disallowedCharacterSet) returns the range of the first disallowed character. If it doesn’t have any disallowed characters, it returns nil.

Limiting the number of characters that can be entered into a given text field

Now that we’ve restricted numberField to a small set of characters — the digits 0 through 9 and the . and characters — let’s set a maximum number of characters that numberField can contain; let’s make it 6.

Here’s what our code looks like with this new constraint:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
  var result = true
  let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
  
  if textField == numberField {
    if count(string) > 0 {
      let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet
      let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
      
      let resultingStringLengthIsLegal = count(prospectiveText) <= 6
      
      result = replacementStringIsLegal &&
               resultingStringLengthIsLegal
    }
  }
  return result
}

First we determine the prospective text — that is, what the text field would contain if we allow the user’s changes. We do this by using the stringByReplacingCharactersInRange:withString: method, which accepts a range of characters to be replaced, and the string to replace that range of characters.

Note that we have to cast textField.text into an NSString first; that’s because Swift’s String class’ stringByReplacingCharactersInRange:withString: method expects a range in Range<String.Index> format, and we’re working with a range specified as an NSRange. Good ol’ NSString‘s stringByReplacingCharactersInRange:withString: method takes its range as an NSRange.

Once we have the prospective text, we simply check its length. If it’s greater than 6, we have the method return false, which means that the text field simply won’t accept any more than 6 characters.

Confirming that the value entered into a text field is numeric

Let’s add one more constraint to our text field: let’s make sure that only proper numeric values can be entered into the text field. Even though we’ve restricted the user to entering the digits 0 through 9 and the . and characters, it’s still possible to enter non-numeric values such as:

  • 1.2.3 (more than one decimal point), and
  • 4-5 (placing the unary minus anywhere other than at the start of the number).

Let’s add some code to disallow such entries:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
  var result = true
  let prospectiveText = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
  
  if textField == numberField {
    if count(string) > 0 {
      let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet
      let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil
      
      let resultingStringLengthIsLegal = count(prospectiveText) <= 6
      
      let scanner = NSScanner(string: prospectiveText)
      let resultingTextIsNumeric = scanner.scanDecimal(nil) && scanner.atEnd
      
      result = replacementStringIsLegal &&
               resultingStringLengthIsLegal &&
               resultingTextIsNumeric
    }
  }
  return result
}

What powers this constraint is NSScanner, which is a great tool for parsing string data. We’re using two of its methods:

  • scanDecimal(_:), which returns true if the scanner finds a valid NSDecimal representation in the string, and
  • atEnd, which returns true if the scanner has scanned the entirety of the string.

With the final code shown above, we’ve got a way to ensure that the user can enter only numeric values into a text field, and that those values no longer than a specified number of characters. Contrary to what was implied in Beginning iPhone Development with Swift, it wasn’t all that hard to do.