Tuesday, August 24, 2010

Apple’s iTunes U Passes 3,000,000 Downloads

In a little over three years Apple’s iTunes U has gone from a small selection of videos and podcasts from a hand full of schools to a juggernaut of open learning with more than 800 universities throughout the world.

iTunes U is a great place for those who love to learn and with the release of iTunes 9 iTunes U has a tab prominently displayed alongside Music, Movies, TV Shows, App Store and Podcasts allowing for easy access to content.
“iTunes U makes it easy for people to discover and learn with content from many of the world’s top institutions,” said Eddy Cue, Apple’s vice president of Internet Services.
iTunes U has more than 350,000 videos and podcasts from world class institutions such as Harvard, MIT, Cambridge, Oxford, University of Melbourne, Université de Montréal and new content has just been added from universities in China, Hong Kong, Japan, Mexico and Singapore.

By The Numbers
Approximately 800 institutions produce content for iTunes U with and average of 437.5 media clips per institution.  As there have been 3,000,000 downloads of the 350,000 videos and podcasts the average download per media clip is 8.57.  But several clips have a much higher download rate such as Stanford University’s iPhone Application Programming course.

Friday, August 20, 2010

iPad Friday: August 20, 2010

Hello and happy Friday.  Today's iPad wallpapers continue the exploration of light and shadow with objects presented on a stage.  Enjoy!

(click an image for the full-size wallpaper)

iPhone Friday: August 20, 2010

Hello and happy Friday.  Today's iPhone wallpapers continue the exploration of light and shadow with objects presented on a stage.  Enjoy!

(click an image for the full-size wallpaper)

Friday, August 13, 2010

iPad Friday: August 13, 2010

Hello and happy Friday.  Today's iPad wallpapers continue the exploration of light and shadow with an added splash of organic symmetry.  Enjoy!

(click an image for the full-size wallpaper)

iPhone Friday: August 13, 2010

Hello and happy Friday.  Today's iPhone wallpapers continue the exploration of light and shadow with an added splash of organic symmetry.  Enjoy!

(click an image for the full-size wallpaper)

Monday, August 9, 2010

Apple announces App Store Volume Purchase Program

Today Apple announced the App Store Volume Purchase Program giving you the ability to provide a volume discount for your app to (currently) educational institutions.

With the App Store Volume Purchase Program, education institutions in the United States can purchase your applications in volume for distribution to their students and faculty.

More information for registered developers can be found by logging into Apple Developer Center or iTunes Connect.  The App Store VPP service page states you can choose to offer special pricing that is 50% of your list price to education institutions when they purchase 20 or more copies of your app and you have the option to apply this special pricing to all of your applications or only individual applications.

This can be a good incentive for educational institutions to purchase your apps but they still have to know that the app exists to consider the purchase, so marketing and direct contact with the institutions would still be critical to your sales stratigy.

Loading device specific .xib files in a Universal app

While working on the update to Fridgemags I came across an issue loading the proper .xib file for the correct device.  Apple docs state that the device will dynamically load the correct corresponding files using the following convention: <mainName><device_modifier>.<filename_extension>.  That is to say if you have MainView.xib and MainView~ipad.xib in the same location and it should load the correct .xib file

Now, Apple's documentation may say one thing but due to the organization of our code, an issue with the simulator or Apple's implementation I was not getting the correct .xib file to load for the correct device.  Also, this does not work with older versions of iOS.

To allow for these exceptions I've replaced the standard init method:
- (id)init {
  self = [super initWithNibName:@"MainView" bundle:nil];
  if ( ! self) return nil;

With the following init method:
- (id)init {
  NSMutableString *nibName = [NSMutableString stringWithString:@"MainView"];
  if ([UIDevice instancesRespondToSelector:@selector(userInterfaceIdiom)]) {
    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
      [nibName appendString:@"~ipad"];
  self = [super initWithNibName:nibName bundle:nil];
  if ( ! self) return nil;

Now the app will check to see if UIDevice responds to userInterfaceIdiom and if it's UIUserInterfaceIdiomPad then load the MainView with "~ipad" appended to it.

This can be further simplified by creating a category and creating a new method such as initWithUniversalNibName:bundle:.

Friday, August 6, 2010

iPad Friday: August 6, 2010

Hello and happy Friday.  Today's collection of iPad wallpapers continue our study of light and shadow but with the addition of reflection taking inspiration from spheres.  Enjoy!

(click an image for the full-size wallpaper)

iPhone Friday: August 6, 2010

Hello and happy Friday.  Today's collection of iPhone wallpapers continue our study of light and shadow but with the addition of reflection taking inspiration from spheres.  Enjoy!

(click an image for the full-size wallpaper)

Thursday, August 5, 2010

How to get the file extension for a mime type on iOS

I was working on some code that downloads and saves images from the web to the iPhone and iPad, and wanted to use the correct extension on the filename. In this case, the image is coming from a URL like http://example.com/apps/mycoolapp/icon, where a web application is returning the image data dynamically, so I can't use the extension from the filename part of the URL.

I could just save the image data in a file named "icon" with no extension, since the UIImage class will look at the header in the image data to determine the true image type. Neither the filename extension nor the mime type in the Content-Type response header is reliable in general, but in this case I wrote the web application that my iPhone app is talking to, so I can make sure the Content-Type in the response is reliable.

So now all I need is a way to turn a mime type into a file extension. Rather than build my own table that maps mime types to extensions, I though there might be a way to get this from iOS. Turns out there is: Uniform Type Identifiers, which are available on both iOS and Mac OS X. On iOS, first add the MobileCoreServices framework to your project, then import the <MobileCoreServices/MobileCoreServices.h> header. On Mac OS X, add the CoreServices framework and import <CoreServices/CoreServices.h>

A Uniform Type Identifier (UTI) is simply a string like public.png or com.apple.pict that identifies a file or directory type. Proprietary formats use a reverse DNS naming scheme while common formats begin with public. Additionally, third party developers can define UTIs for their application data formats. UTIs are typically associated with one or more file extensions and mime types. In UTI parlance, extensions and mime types are "tags".

If you have a mime type, you can get the UTI for it using the UTTypeCreatePreferredIdentifierForTag() function. To get the UTI for image/png:
// get a UTI for a mime type
CFStringRef mimeType = (CFStringRef)@"image/png";
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
// uti now equals "public.png"
Since this is a procedural API, Core Foundation memory management rules are in effect. You are the owner of the CFStringRef returned by UTTypeCreatePreferredIdentifierForTag() and are responsible for calling CFRelease() on it. Alternately, since CFStringRef is toll-free bridged to NSString, you can cast the returned CFStringRef to a NSString* and call the -release or -autorelease method.

Once you have the UTI, you can get the extension for it. The UTTypeCopyPreferredTagWithClass() function takes a UTI and returns the first "tag" of the desired class (extension or mime type):
// get an extension for a UTI
CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);
As with UTTypeCreatePreferredIdentifierForTag(), you own the CFStringRef returned by UTTypeCopyPreferredTagWithClass() and must CFRelease() it or cast it to NSString* and -release or -autorelease it.

You can easily reverse this process by switching the tag class constants kUTTagClassMIMEType and kUTTagClassFilenameExtension in the examples. There's a little bit more to UTIs than I've covered here. The Uniform Type Identifiers Overview explains all the concepts behind UTIs and tags. The UTType Reference details all the functions and constants. Finally, Uniform Type Identifiers Reference lists all the system defined UTIs and their associated tags.

Tuesday, August 3, 2010

Objective-C Tuesdays: concatenating strings

Last week we reviewed wide character strings. Today we'll begin looking at common string operations using C strings and NSStrings, starting with string concatenation.

Many languages have built in support for string concatenation, but C and Objective-C isn't among them. Instead, joining strings is accomplished using library functions in C and member functions of the NSString class in Objective-C.

C strings
Concatenating two C strings is particularly error prone, since it typically requires manually calculating the required buffer size and allocating it.
// concatenating two C strings
char const *s1 = "foo";
char const *s2 = "bar";
size_t size = (strlen(s1) * sizeof(char)) + (strlen(s2) * sizeof(char)) + sizeof('\0');
char *s3 = malloc(size);
if (s3) {
  strcpy(s3, s1);
  strcat(s3, s2);
} else {
  // handle memory allocation failure
Exploring this code in logical chunks, the first two lines are specific to this example: they define the two strings we're going to join, s1 and s2. The next line calculates the number of bytes required to hold the new string.
// calculate size of new string
size_t size = (strlen(s1) * sizeof(char)) + (strlen(s2) * sizeof(char)) + sizeof('\0');
The strlen() function counts the number of chars in a string, not including the null terminator. To be pedantically correct, we multiply the length of each string by the size of a char, but since the char integer type is one byte in size, we can write the size calculation this way instead:
size_t size = strlen(s1) + strlen(s2) + sizeof('\0');
If we were concatenating two wide character strings instead, we wouldn't be able to take that shortcut:
size_t size = (wcslen(ws1) * sizeof(wchar_t)) + (wcslen(ws2) * sizeof(wchar_t)) + sizeof(L'\0');
As a matter of style, I like to use the expression sizeof('\0') to account for the size of the null terminator, but it's more common to simply add one:
size_t size = strlen(s1) + strlen(s2) + 1;
The malloc() function allocates a block of memory. If malloc() succeeds, it returns a non-NULL pointer to the memory you requested.
char *s3 = malloc(size);
After checking that the value of pointer s3 is not NULL, we first call strcpy() ("string copy") to copy the string pointed to by s1 into the memory pointed to s3.
if (s3) {
  strcpy(s3, s1);
The strcpy() function always places a null terminator at the end of the destination string. When strcpy() returns, s1 and s3 point to identical C strings at different locations in memory.

Finally, we call strcat() ("string catenate") to append s2 to the end of s3. ("Catenate" is a synonym for "concatenate". Isn't English strange?)
strcat(s3, s2);
The strcat() function first walks down the destination string until it finds the null terminator, then it copies the source string there, overwriting the original null terminator and putting a new null terminator at the end of the appended string. When using strcat() you need to be sure that the destination memory block contains enough space to hold the concatenated strings. If it's too small, you will overwrite memory some other memory block, causing data corruption or a program crash.

If there isn't enough memory available, malloc() returns NULL.
if (s3) {
  // ...
} else {
  // handle memory allocation failure
Checking this return value is important; trying to use a NULL pointer will cause your program to be killed by the system. Unfortunately handling errors like this deep in your code is generally a pain in the butt; frequently there's no good option except to abort the current operation.

using a fixed buffer
If you know the maximum size of the strings before hand and the concatenated string is an intermediate value, you can often use a fixed buffer instead of a call to malloc():
// concatenating two C strings
// using a fixed buffer
char const *s1 = "foo";
char const *s2 = "bar";
char buffer[80];

strcpy(buffer, s1);
strcat(buffer, s2);
// buffer now holds concatenated strings
This greatly simplifies C string concatenation, but if your input strings are too big, you'll overflow your buffer and cause a program crash.

Appending one NSString to another is pretty straight forward. The -stringByAppendingString: instance method performs string concatenation, returning a new NSString instance
// concatenating two NSStrings
NSString *s1 = @"foo";
NSString *s2 = @"bar";
NSString *s3 = [s1 stringByAppendingString:s2];
The resulting NSString (s3) is autoreleased and contains "foobar".

appending a formatted string
There's an alternate way to do NSString concatenation by using -stringByAppendingFormat:
// concatenating two NSStrings using a format
NSString *s1 = @"foo";
NSString *s2 = @"bar";
NSString *s3 = [s1 stringByAppendingFormat:@"%@", s2];
Here, we specify a format string that contains an object replacement (%@) only. Additional arguments after the format string must match the replacement specifiers in the format string. This method first generates the formatted string then appends it to the receiver (s1). It's not as efficient as using -stringByAppendingString: directly, but it's more flexible. You can just as easily append an integer or a C string:
NSString *s1 = @"foo";

// appending a number
NSString *s2 = [s1 stringByAppendingFormat:@"%i", 1234];
// s2 is "foo1234"

// appending a C string
char const *s3 = "bar";
NSString *s4 = [s1 stringByAppendingFormat:@"%s", s3];
// s4 is "foobar"

NSString preferred
It should be apparent that NSString concatenation is much easier to deal with than the multi-step procedure required for C strings. In iOS programs, you should generally use NSString whenever possible.

Next time, we'll look at comparison operations and equality of C strings and NSStrings.