Forge Code

UIFont Name Grabber

It’s been a long time between posts here on Forge Code. Since my last post, I’ve made the transition to become a full time freelance iPhone/iPad developer, which, alongside various personal and family events, has meant that my time has been at a premium. This doesn’t mean that I don’t have anything to write about - in fact, quite the opposite. I now have a bunch of topics and snippets queued up in the back of my brain, it’s just a matter of finding the time to get them out into the aether.

Now, onto the actual post…

Creating UIFont objects

The most common method of creating or representing fonts in code in iOS is to use +[UIFont fontWithName:size:]. It’s very straightforward to use: to get a UIFont instance that represents Helvetica 12 point, you would do this:

UIFont *font = [UIFont fontWithName:@"Helvetica" size:12.0];

This is simple, but what’s not so simple is knowing what string you would use to select font variations like Helvetica Bold or Helvetica Oblique. The string argument passed to fontWithName:size: needs to be one of a pre-defined list of available system fonts (or, on iOS 3.2 and later, an imported font). UIFont allows you to get the list of available ‘family names’ (e.g. Helvetica), and then the list of ‘font names’ that belong to a particular ‘family’ (e.g. Helvetica, Helvetica-Bold, Helvetica-BoldOblique and Helvetica-Oblique) by using the +familyNames and +fontNamesForFamilyName: class methods. The strings returned by +fontNamesForFamilyName: are the values that can be used as an argument for +fontWithName:size:. Writing code to iterate through these lists is easy enough, but it’s tedious having to do it every time you want to access to what should really be part of the Cocoa Touch API reference documentation.

UIFont Name Grabber

To get around this problem, I’ve written a very simple universal iOS app that grabs these lists of fonts, serialises them into both plain text and XML plist formats, then attaches them to an email. Email seemed like the most straightforward way of getting files from any iOS device to a development Mac. The attachments have the OS version number in the filename, so it’s easy to gather these files from different OS versions and compare the available fonts. I’ve tested the app on iPhone OS 3.1.3, 3.2.1 and 4.0.1.

Here’s the code that grabs (and formats) the lists of fonts:

NSMutableDictionary *fontsByFamilyName = [NSMutableDictionary dictionary];
NSMutableString *fontsString = [NSMutableString string];

NSArray *sortDescriptors = [NSArray arrayWithObject:[[[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES] autorelease]];

NSArray *familyNames = [[UIFont familyNames] sortedArrayUsingDescriptors:sortDescriptors];
for (NSString *aFamilyName in familyNames) {
  NSArray *fontNames = [[UIFont fontNamesForFamilyName:aFamilyName] sortedArrayUsingDescriptors:sortDescriptors];

  [fontsByFamilyName setObject:fontNames forKey:aFamilyName];

  [fontsString appendFormat:@"%@\n", aFamilyName];
  for (NSString *aFontName in fontNames) {
      [fontsString appendFormat:@"\t%@\n", aFontName];
  }
  [fontsString appendString:@"\n"];
}

// Create an XML plist data representation of the dictionary
NSData *fontsPlistAsData = [NSPropertyListSerialization dataFromPropertyList:fontsByFamilyName
                                                                    format:NSPropertyListXMLFormat_v1_0
                                                          errorDescription:nil];

// Create a UTF8 data representation of the string
NSData *fontsTxtAsData = [fontsString dataUsingEncoding:NSUTF8StringEncoding];

The app is freely available on github here: UIFont-Name-Grabber. Hopefully others will find it as useful as I do.

Comments