Category Archives: iOS Development

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:





What is the NSPhotoLibrary Usage Description key?

Since iOS 10 and Xcode 8, Apple have added (yet another) security check for our apps. This time it’s about our apps accessing the user’s photo library.

While it was a courtesy to ask the user for permission to use the library before, since iOS 10 we have to add a special key to the app target’s Info.plist file and give a reason why we want to have access.

Here’s how to do it:

Navigate to your project’s target and select the Info tab at the top. In the long list below, hover over any row and click on the little plus icon that comes up. This should add a new row to the table (or in other words, add an entry to the Info.plist file).

Now type in NSPhotoLibraryUsageDescription. It should automatically turn into “Privacy – Photo Library Usage Description”.

On the right hand side of your new row we can add a string value, which will become the description in the dialogue shown in the screenshot above. It seems that we’re free to add whatever we want here, explaining briefly that your app needs access to the user’s photos.

That’s it!

On this note, there are two other keys that may come in handy for accessing the user’s camera and microphone respectively:

  • NSCameraUsageDescriptionKey
  • NSMicrophoneUsageDescriptionKey

Just as with photos, add these keys and a brief description if your app needs access to either the camera or the microphone. Something like “for image sharing” should do nicely. Here’s what that message looks like in context when iOS presents the dialogue to the user:

The dialogue is shown only once, not every time when the user wants to share an image. Should the user decline, or should s/he want to change this, we should explain to them that this can be done under iOS Settings – Privacy – Photos.

Demo Project

I’ve updated my Demo Project on GitHub with the relevant changes so that it now runs correctly under iOS 10:

For an extensive list of other useful NSkeys, check out this Stack Overflow thread:





How to delete a git branch with Xcode 8

Recently  I tried to merge some changes I had made on another branch back into my master branch, but Xcode wouldn’t let me. Spurious error messages prevented this from happening. I was happy to simply create a new master branch and overwrite it completely with the changes I had implemented on my former testing branch.

Turns out that Xcode is happy to create new git branches for our projects and screw them up several times in a row, but sadly, it is not capable of deleting branches.

So the simple answer to the title of this post is: it can’t be done!

However, a quick command in Terminal can do it for is. cd into your local project directory and issue the following:

git branch -D yourbranch

where “yourbranch” is of course the name of your branch. Make sure you’re not currently on the branch you try to delete.

Doing this allowed me to simply create a new branch using Source Control – New Branch. When we do that, Xcode will automatically use the contents of our current branch as a starting point for the new branch and switch us onto it immediately.