Thomas Denney

New fonts in iOS 7

When Apple releases new versions of iOS they often add new default fonts, and iOS 7 is no different - although maybe especially notable for its thin variants of Helvetica Neue, which is one of almost 40 new font styles added in iOS 7. The following list was generated by listing the fonts on an iOS 6 device with a couple of handy methods on UIFont, doing the same on iOS 7, finding the differences with a simple Python script and then creating a simple table view which I screen shotted. I’ve also got the full lists on my GitHub account.

The new fonts

  • AlNile
  • AlNile-Bold
  • AppleSDGothicNeo-Light
  • AppleSDGothicNeo-Regular
  • AppleSDGothicNeo-SemiBold
  • AppleSDGothicNeo-Thin
  • ArialHebrew-Light
  • Damascus
  • DamascusBold
  • DamascusMedium
  • DamascusSemiBold
  • DINAlternate-Bold
  • DINCondensed-Bold
  • DiwanMishafi
  • Farah
  • GeezaPro-Light
  • HelveticaNeue-MediumItalic
  • HelveticaNeue-Thin
  • HelveticaNeue-Thin_Italic
  • IowanOldStyle-Bold
  • IowanOldStyle-BoldItalic
  • IowanOldStyle-Italic
  • IowanOldStyle-Roman
  • Menlo-Bold
  • Menlo-BoldItalic
  • Menlo-Italic
  • Menlo-Regular
  • SavoyeLetPlain
  • Superclarendon-Black
  • Superclarendon-BlackItalic
  • Superclarendon-Bold
  • Superclarendon-BoldItalic
  • Superclarendon-Italic
  • Superclarendon-Light
  • Superclarendon-LightItalic
  • Superclarendon-Regular
  • Thonburi-Light

Image of all the new fonts

New fonts

Enumerate characters of an NSString

The following category method will allow you to iterate over the characters of an NSString with a block:

-(void)enumerateCharacters:(EnumerationBlock)enumerationBlock
{
    const unichar * chars = CFStringGetCharactersPtr((__bridge CFStringRef)self);
    //Function will return NULL if internal storage of string doesn't allow for easy iteration
    if (chars != NULL)
    {
        NSUInteger index = 0;
        while (*chars) {
            enumerationBlock(*chars, index);
            chars++;
            index++;
        }
    }
    else
    {
        //Use IMP/SEL if the other enumeration is unavailable
        SEL sel = @selector(characterAtIndex:);
        unichar (*charAtIndex)(id, SEL, NSUInteger) = (typeof(charAtIndex)) [self methodForSelector:sel];
        
        for (NSUInteger i = 0; i < self.length; i++)
        {
            const unichar c = charAtIndex(self, sel, i);
            enumerationBlock(c, i);
        }
    }
}

Keep Calm updated

I’ve added the following new features to Keep Calm 2.31:

  • A ton of bug fixes, the app is a lot more solid now
  • Pro users can now crop, scale and rotate their custom icons (this feature will probably be added to the background import at some point soon too)
  • Purchasing upgrades is now a lot faster. Technical explanation: Previously when you pressed to purchase an upgrade it made a request for the information about the product from Apple, meaning there was a delay of a few seconds whilst this information was received and processed. Now as soon as you enter the store the information is fetched, so payment now has one less step, making the whole thing a lot faster :)

Creating iOS app icons with a shell script

One of the more annoying parts of working on iOS project is generating all of the appropriate artwork - there are up to 13 different images that you have to create just for the app icon. Several apps exist for this, however I figured a simpler solution would be to have a simple shell script:

#!/bin/sh

ITUNES_ARTWORK="$1"
FOLDER=$(dirname "$ITUNES_ARTWORK")

sips -z 57 57 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon.png"
sips -z 114 114 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon@2x.png"
sips -z 120 120 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-60@2x.png"
sips -z 29 29 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small.png"
sips -z 58 58 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small@2x.png"
sips -z 40 40 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small-40.png"
sips -z 80 80 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small-40@2x.png"
sips -z 50 50 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small-50.png"
sips -z 100 100 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-Small-50@2x.png"
sips -z 72 72 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-72.png"
sips -z 144 144 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-72@2x.png"
sips -z 76 76 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-76.png"
sips -z 152 152 "$ITUNES_ARTWORK" --out "${FOLDER}/Icon-76@2x.png"

Here’s what you need to do to set it up:

  • Save the above into a file in your home directory called icongenerator.sh (it is imperative that it is in your home directory)
  • Open up terminal and execute ‘chmod +x icongenerator.sh’
  • Execute ‘./icongenerator.sh path/to/iTunesArtwork’
  • The script will then create the new image files

In case you haven’t come across it before, sips is a really simple way of quickly resizing images on the command line on OSX.

Blurred Camera updated

After seeing a successful opening weekend, I’ve updated Blurred Camera with the following new features:

  • Updated icon (i.e. it actually looks alright now)
  • Fixed bug with the spinner staying on screen for ages when importing a photo
  • Major performance enhancements, especially when importing a photo
  • Much smaller app bundle size (75% smaller, mostly due to PNG compression of the icons and launch images)

Introducing Blurred Camera

Blurred Camera

Blurred Camera is a new free iOS app that I’ve been working on that makes it really easy to create blurry photos that you can use as your wallpaper. The app allows you to vary how much the image is blurred by pinching and also allows you to adjust the brightness and saturation by swiping.

The app is really quite simple (I threw it together in a couple of evenings) and based off of GPUImage.

Parsing HTML with AFNetworking 2 and ObjectiveGumbo

Now that AFNetworking 2 is out and ObjectiveGumbo is now available on CocoaPods I thought I would write a simple guide showing you how you can build a simple app that uses HTML files as a data source through AFNetworking. This post shows how to write an app that will find the top read articles on BBC News, list them and allow the user to visit them. You can find the source in the ObjectiveGumbo demos repository.

Setting up CocoaPods

AFNetworking 2 currently requires iOS 7 due to its new reliance on NSURLSession (a new iOS 7 framework for working with URL requests and connections), so you’ll need to add the following to your Podfile and execute ‘pod install’ to download the dependencies:

platform :ios, '7.0'
pod "ObjectiveGumbo", "0.1"
pod "AFNetworking", "2.0.0-RC3"

If you are unfamiliar with CocoaPods, they have a setup guide on their website.

An HTML serializer

One of the great new features of AFNetworking 2 is that serializers are now abstracted away from the core URL requesting code. This means that you can easily write a response serialiser that will take an NSData object and convert it into something useful - AFNetworking ships with classes that you can subclass that will serialize XML or JSON into NSDictionarys for example.

To build a custom response serializer to decode the NSData response from the web server into an OGDocument (the base class of a document parsed by ObjectiveGumbo) you will need to subclass AFHTTPResponseSerializer into HTMLResponseSerializer and implement the following method:

-(id)responseObjectForResponse:(NSURLResponse *)response
    data:(NSData *)data 
    error:(NSError *__autoreleasing *)error
{
    return [ObjectiveGumbo parseDocumentWithData:data];
}

(The full code for the .h and .m files are in the repo linked above)

Subclassing the HTML serializer

Whilst having the data as an OGDocument might be fine for your application, you will probably want to feed it back custom objects that are relevant to your application. In this example I’m going to parse the list on the BBC site of most read articles and put it into an Article class with a link and title.

You will need to subclass the HTMLResponseSerializer into BBCResponseSerializer, and again implement the responseObjectForResponse:data:error: method:

-(id)responseObjectForResponse:(NSURLResponse *)response 
     data:(NSData *)data
     error:(NSError *__autoreleasing *)error
{
    //1
    OGDocument * document = [super responseObjectForResponse:response
                                                        data:data 
                                                        error:error];

    //2
    NSArray * panels = [document select:@".panel"];

    NSMutableArray * articles = [NSMutableArray new];

    //3
    //The list of most read articles is in the second panel
    OGElement * list = (OGElement*)[panels[1] first:@"ol"];

    //4
    for (OGElement * listItem in [list select:@"li"])
    {
        //5
        OGElement * link = (OGElement*)[listItem first:@"a"];
        NSString * href = link.attributes[@"href"];
        //Whitespace and the span are the first two elements
        NSString * title = [link.children[2] text];
        //6
        Article * article = [Article new];
        article.title = title;
        article.link = [NSURL URLWithString:href];
        [articles addObject:article];
    }

    //7
    return articles;
}
  1. The data is first parsed using the super class (HTMLResponseSerializer) to get an OGDocument object (which is a subclass of OGNode that also contains DOCTYPE information, although we won’t need it for this example)
  2. ObjectiveGumbo has a jQuery/CSS like selection system that makes it easy to select elements in the DOM. Here we select all of the elements that have the class ‘panel’ (the list of Top Shared, Top Read and Top Shared on the right all have this class)
  3. Again, use the select method to pick the first ordered list from the second panel (the top read panela)
  4. Iterate over all of the list items
  5. Get the link and its href attribute and get the title of the link as well (you may wish to look at the page source for the BBC News homepage if this is confusing)
  6. Put the data into a custom Article class that can be used by the primary view controller
  7. The superclass would ordinarily return an OGDocument, however for this request we instead return a list of articles

Using the data

Now that we’ve written methods for parsing the data, presenting it is fairly trivial. Here is the code for my master view controller:


- (void)viewDidLoad
{
    [super viewDidLoad];

    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://bbc.co.uk/news"]];
    AFHTTPRequestOperation * operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    operation.responseSerializer = [BBCResponseSerializer serializer];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        self.articles = (NSArray*)responseObject;
        [self.tableView reloadData];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"%@", error.localizedDescription);
    }];
    [operation start];
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.articles.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    Article * article = self.articles[indexPath.row];

    cell.textLabel.text = article.title;
    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        Article * article = self.articles[indexPath.row];
        [[segue destinationViewController] setDetailItem:article];
    }
}

ObjectiveGumbo now available via CocoaPods

I’m pleased to announce that if you want to use ObjectiveGumbo, my Objective-C wrapper around Google’s awesome HTML5 parser Gumbo, in your iOS projects you can now install it via CocoaPods. Simply add the following to your podfile to get started:

platform :ios, '6.0'
pod "ObjectiveGumbo", "0.1"

You will then need to run pod install and open the Xcode workspace file, not your project. You can then import the ObjectiveGumbo.h file into your project to begin working with it.

I soon plan to publish a guide that will help you get started using ObjectiveGumbo with AFNetworking 2.

Multi Timer updated for iOS 7

Apple has now approved the updated version of another of my apps, Multi Timer. The new update to Multi Timer vastly enhances the UI on iOS 7, fixes a few bugs and adds a few more icons for your timers.

Head over to the App Store to download Multi Timer for $0.99.

Keep Calm updated for iOS 7

Keep Calm

The new version of Keep Calm 2.3, which has been enhanced for iOS 7, is now available. This version introduces a slightly new UI (it looks very similar to the old one, except that it is now using iOS 7, rather than custom, components) and fixes a bunch of bugs:

  • All in app purchases now work correctly across devices
  • Fewer crashes (I’ve also added crash reporting so hopefully they’ll get resolved quicker in the future)
  • A bunch of new backgrounds
  • Full support for the iPhone 5S
  • Full support for iOS 7
  • A really neat new parallax style effect where you tilt the device and the text on your poster moves, making it seem 3D
  • Posters now fill the screen so they are no longer weird proportions on iPads

You can head over to the App Store now to update (or if you’re using iOS 7 it will download automatically!).