HTTP basic access authentication with Objective-C and iOS

iOS SDKIn this blog post I am going to show how you can make an HTTP request to a webserver that supports basic access authentication using Objective-C and the iOS framework. Regretfully, I don’t have the time to create an Xcode project as an example. But the information and code should give you an idea of how you can build basic access authentication support in your iOS code.

Before we dive into the code, let’s do a quick review of how basic access authentication works. Before an HTTP request is sent to the server, we need to append an HTTP header called Authorization to the request. Here are the steps to generating the Authorization HTTP header:

Using username = myusername and password = mypassword as reference.

  1. Concatenate user name + colon + password. ie. “myusername:mypassword”
  2. Encode the concatenated string with the base64 algorithm. ie. “myusername:mypassword becomes” “bXl1c2VybmFtZTpteXBhc3N3b3Jk”
  3. Append the Base64 encoded string to the “Basic ” string. ie. “Basic bXl1c2VybmFtZTpteXBhc3N3b3Jk”
  4. Finally assign the value to the Authorization header

In Objective-C code, the above logic is translated to:

NSString *authStr = [NSString stringWithFormat:@"%@:%@", @"myusername", @"mypassword"];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:@"Basic %@", [authData base64Encoding]];
[request setValue:authValue forHTTPHeaderField:@"Authorization"];

Just one problem, NSData doesn’t inherently support Base64 encoding. We need to add Base64 encoding algorithm to NSData via Category, a mechanism Objective-C that allows programmers to extend an existing class without subclassing it. Anyway, you can download the Base64 encoding code below.

NSData+Additions source code

Credits and Reference:

Note that you can certainly implement Base64 encoding using C functions or by other means. But I find Category most intuitive to achieving our goal.

Tip
If you are still stuck, use the curl command on a shell to troubleshoot. Here are some examples:

% curl -v -H 'Authorization: Basic bXl1c2VybmFtZTpteXBhc3N3b3Jk' 'http://host/path'

% curl -v --trace-ascii dump.txt 'http://myusername:mypassword@host/path'

Creating multi-variants of an iOS app from a single Xcode project

iOS SDKWhen someone at work asked me about creating multiple variants of an iOS app  from a common codebase (ie. from a single Xcode project), I thought couldn’t this be achieved through defining multiple targets in that Xcode project?

I have done this before for a project where I created a “lite” version and an “HD” (iPad-only) version from a full-featured iPhone codebase I originally created. I was about to document the process on this post before coming across this blog post from Just2Us, which does a great job in explaining the entire process. Instead of duplicating the content, just refer to the blog post.

One thing I would do differently from what is described in the referenced post is that instead of adding a new target, I would recommend duplicating an existing target – this way I avoid the hassle of configuring the new build target and including the files to my target phases manually.

Duplicating a build target in Xcode

I have also created a project to demonstrate the multi-target in Xcode. You can download the file here.

Quick guide to iOS dateformatting

iOS SDK

This blogpost will focus on the setDateFormat: method of NSDateFormatter which allow us to define the date format of the textual representation of the date and time in iOS/Cocoa. Here’s a summary of the specifiers used in the date format string.

The most commonly used date format specifiers are (keep in mind that they are case sensitive):

  • y = year
  • Q = quarter
  • M = month
  • w = week of year
  • W = week of month
  • d = day of the month
  • D = day of year
  • E = day of week
  • a = period (AM or PM)
  • h = hour (1-12)
  • H = hour (0-23)
  • m = minute
  • s = second

In general, the number of characters in a specifier determine the size of date field. Let’s use an example to illustrate date formatting.

eg. Input date = 2011-05-01 Sunday

1-character = 1-digit/character number or word (if number/word can’t be 1 character long then abbreviation or fullname is displayed).

[dateFormatter setDateFormat:@"E, d M y"];  // Output: Sun, 1 5 2011

2-character = 2-digit/character number or word (if number/word can’t be 2 character long then abbreviation is displayed).

[dateFormatter setDateFormat:@"EE, dd MM yy"];  // Output: Sun, 01 05 11

3-character = 3-digit/character number or word, or abbreviation (generally).

[dateFormatter setDateFormat:@"EEE, ddd MMM yyy"];  // Output: Sun, 001 May 2011

4-character = full name (generally).

[dateFormatter setDateFormat:@"EEEE, dddd MMMM yyyy"];  // Output: Sunday, 0001 May 2011

Here’s the weird part though, if you specify 5 E’s, you get an rather unexpected output. You would think that the output date field would be longer than 1 character:

[dateFormatter setDateFormat:@"EEEEE, ddddd MMMMM yyyyy"];  // Output: S, 00001 M 2011

For date formatting, the following reference table has been very useful:

Date Field Symbol Table (UTS #35 Unicode Locale Data Markup Language)