Category Archives: iOS Development

Building a Day Counter on iOS – Part 1

In this series I’ll show you how to create a simple Day Counter on iOS, using Objective-C and Xcode 9. The idea is to set a date in a settings screen, and then see how many days have elapsed on the main screen right after launching the app.

This is a 3-Part Mini-Series:

  • Part 1 is all about building the interface in Interface Builder
  • Part 2 is about coding the NSDate subtraction methods, using NSCalendar and loading/saving data using NSUserDefaults
  • Part 3 will introduce Key/Value Observing to update the first view controller as soon as the date is changed in the settings and deals with how to normalise an NSDate object.

You can find the full code on GitHub:

Happy Hacking!

How to pick a random character from a string in Objective-C

Imagine we had an NSString consisting of a pool of characters from which we’d like to pick one at random. Say our pool is ABCDEFGHIJKLMNOP, and we want a single character.

Here’s how we can do that:

// pool of characters
NSString *characters = @"ABCDEFGHIJKLMNOP";

// create a random number 
// between 1 and however many characters we have in the pool
uint32_t length = (uint32_t)characters.length;
NSUInteger random = arc4random_uniform(length);

// make a range
NSRange range = NSMakeRange(random, 1);

// pick a random character from the pool
NSString *letter = [characters substringWithRange:range];

The comments speak for themselves. One thing of note is the typecast of characters.length, which is needed to suppress the Xcode warning “implicit conversion loses integer precision”.

Most of the magic is provided by the NSString method substringWithRange.

How to use Version Control since Xcode 9

Xcode 9 has introduced a few changes in regards to Version Control is now handled. If you’re looking for the once so proud Source Control – Configure menu option, you’ll find that it’s no longer there. Dang! Where has it gone, and how are we supposed to manage our projects now?

Turns out there is a new tab in town, next to the Project Navigator (File manager icon) in the left hand pane of Xcode 9, called the Source Control Navigator. Click on it to find a plethora of options:

And would you look at that: for the first time in a decade, we can actually manage Tags as well as Branches here! And we get to see all those commits and comments we’ve been making for years, all without having to use additional version control tools! It’s like Christmas has arrived early!

Here’s a WWDC video on how we’re meant to use the new features from now on. It certainly didn’t answer all the questions I had, so for that, read what I’ve learnt through experimentation further down. Continue reading

How to detect an iPhone X

The iPhone X is like a “glimpse into the future”, according to Apple. By “the future” they mean “this is what three year old Samsung components could look like if they ran iOS”. iPhone X has been described as gimmicky and as “$1k for Face ID, with no other benefits”.

Overall it was not as warmly received as the 10 year anniversary device as it perhaps could have been.

But all that aside, as developers, we still need to support it and perhaps even give the device some unique treatment, be that with a dedicated Storyboard to make use of the larger screen, or to give attention to a feature other phones don’t have. Before we can do that though, we need to figure out a way to test if we’re actually dealing with an iPhone X device.

I know of no better way to do this than the trusted screen height check. Let’s see how this might work. Continue reading

What’s New in iOS 11

I always find it helpful to sum up what’s new in a release, and I can never remember where to find such documents once a release has happened.

So here it is, Apple’s “biggest and best ever release”, iOS 11.

General changes

iOS 11 requires Xcode 9+ to develop your apps. It is the first major release to drop support for 32 bit binaries. The following devices are supported in iOS 11:

  • iPhone 5s and above
  • iPad Air and above
  • iPhone 5, 5c and lower are no longer supported
  • iPad 4 and below are no longer supported

This release also drops native support for integrated services such as Vimeo, Flickr, Facebook and Twitter.

The iCloud Drive app is removed and replaced with the new Files app.

New frameworks we can tinker with are:

  • ARKit for Augmented Reality (requires devices with A9 chip and above)
  • Core ML for Machine Learning (identifying shapes in images, or words in sentences)
  • Depth API to access the dual cameras on iPhone 7, 8 and X
  • Core NFC for (limited) access to the NFC chip in most devices

Continue reading

How to load a different storyboard for different iPad Sizes

Since the introduction of the iPad Pro range, we now have to deal with three distinct iPad screen sizes. And although the 10.5″ and 9.7″ are very similar in size, the giant iPad Pro 12.9″ easily looks shockingly bad when used with a storyboard that otherwise looks handsome on the “smaller” iPad screens.

So what is a dev to do? Prepare a completely different storyboard for an iPad Pro 12.9″ of course! I’ve shown in the past how to do this for different phone sizes, so here’s how to do it for different iPad sizes. This approach will work with iOS 8 and above.

Determining the Screen Height

Sadly Apple have not implemented a new UIUserInterfaceIdiom property we could question. Every iPad device will only identify itself as an iPad rather than an iPad Pro model. But I guess this wouldn’t help us much anyway, since we have three screen sizes as of 2017, with god only knows how many more in the pipeline.

Hence, we need to determine what screen height we’re dealing with. To do this reliably though, we must also know if the user is holding the device in portrait or landscape mode when our app starts, otherwise “height” might be interpreted differently.

Lucky for us, there is a trait collection property we can use to question this, called fixedCoordinateSpace. We can call it on our UIScreen class. Here’s how:

int height = [UIScreen mainScreen].fixedCoordinateSpace.bounds.size.height;
NSLog(@"The fixed height is %i", height);

This test shall be at the heart of our endeavours. When derived like this, height will always deliver the “portrait up” height of our device, regardless if the app starts in portrait or landscape mode.

Now we’ll add another test to it, namely if the device we’re testing is in fact an iPad. If it is, we’ll compare the height parameter to the height of a 10.5″ iPad (which is 1024 pixels, just like it would be for a 9.7″ device). If it’s larger, we’re dealing with a 12.9″ device. And if it’s not an iPad at all, we’ll load an iPhone storyboard.

Here’s how we might do that:

- (UIStoryboard *)grabStoryboard {

    UIStoryboard *storyboard;
    // detect screen height
    int height = [UIScreen mainScreen].fixedCoordinateSpace.bounds.size.height;
    NSLog(@"The fixed height is %i", height);
    // determine if this is an iPad
    if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        // it's an iPad 10.5" or lower
        if (height <= 1024) {
            storyboard = [UIStoryboard storyboardWithName:@"iPad" bundle:nil];
        } else {
            // it's an iPad Pro 12.9"
            storyboard = [UIStoryboard storyboardWithName:@"iPad-Pro" bundle:nil];
    } else {
        // not an iPad, load regular storyboard
        storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    return  storyboard;

In our project we have three storyboards: Main, iPad and iPad-Pro. Each of these will now be returned by this method depending on their screen height.

Displaying our Storyboard

Now that we have a reference to the one we need, let’s load it in our AppDelegate. We’ll do that just before returning YES in the didFinishLaunchingWithOptons method:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // grab and show the storyboard
    UIStoryboard *storyboard = [self grabStoryboard];
    self.window.rootViewController = [storyboard instantiateInitialViewController];
    [self.window makeKeyAndVisible];
    return YES;

It is irrelevant which storyboard is set as the main storyboard in the iOS target, it will be overridden by this method’s last two calls.

Demo Project

I’ve got a demo project on GitHub to demonstrate this, feel free to check it out and tinker with it: