How to convert your iPhone Storyboard into an iPad Storyboard

Sometimes it’s just easier to start from an existing Storyboard rather than build everything again from scratch. Especially so when you want to create an iPad version of your iPhone app.

When you change your deployment info to Universal, Xcode even offers to copy your existing storyboard for you. That’s really nice – but even though it behaves like an iPad storyboard, when you open it in Interface Builder it still looks like you’re creating an iPhone layout. This makes re-arranging things difficult.

Help it at hand with a simple tweak. Under the hood, a Storyboard is just an XML file and as such as a plethora of key/value pairs we can change by hand.

First, make sure you display your layouts in “3.5inch” mode. You can do that by clicking that little icon at the bottom of Interface Builder:

Screen Shot 2014-05-19 at 11.20.25

Next head over to the File Inspector and right-click your storyboard, then select “Open as Source Code”. This will display all that XML code.

Screen Shot 2014-05-19 at 11.08.32

In the second line of the document you’ll find a very long line – somewhere in it you’ll find something like this:

Simply change that line to

This will make Interface Builder display your storyboard with iPad characteristics. All we now have to do is to make it look like a Storyboard again rather than XML code – so head back and right-click on the file again, then select “Open as Interface Builder – iOS Storyboard”.

Watch the full course in one convenient playlist:
Catch this episode on my iOS Dev Diary Podcast:

How to create multiple buttons in a UINavigationBar

Screen Shot 2014-05-17 at 09.54.04Sometimes a single button left and right is just not enough for complex apps. Especially on the iPad we have this large space in the navigation bar. But Interface Builder only allows us to add one button on the left and one on the right.

How do we add more buttons to those spaces? Code is the answer.

Both the left and the right space of a UINavigationBar can take an array of barButtonItems which we can populate with as many buttons as space will allow.

In this example I’m using the Master/Detail template to create an array in the viewDidLoad method of the DetailViewController. This will create the effect shown in the screenshot:

Note how you can create fixed spaces between the buttons as shown.

You can also space those buttons evenly across the whole bar by using the UIBarButtonSystemItemFlexibleSpace, in which case there’s no need to pass the width parameter. When you do, the buttons will be spaced between the right side of the bar and the title if there is one, or across the whole bar if the title is empty.

iCloud in your iOS Apps – Part 5: Initial Import Hack

In this final part of the series I’ll let you in on a little secret that will help our app synchronise iCloud Core Data for the first time when it’s installed on another device.

Some devices it appears don’t display existing iCloud results upon first launch. To remedy this, I’ll show you how to re-fetch the Fetched Results Controller in your sample app.

Watch the whole series

Enjoy!

Watch the full course in one convenient playlist:
Catch this episode on my iOS Dev Diary Podcast:

How to test why your iCloud Core Data store was changed

When you’re using iCloud with Core Data you need to subscribe and react to the NSPersistentStoreCoordinatorStoresDidChange notification. This will tell you when Core Data was able to transition off the “fake” store and is using the “real” store. It will coincide with the log entry “Using local storage: 0”.

Sometimes you need to know why this has happened so you can react accordingly. Here’s how:

When you react to the above, bring the notification object into your even handler method. This will let you query its userInfo dictionary which will hold the key to why the stores have been changed:

Here we grab the NSPersistentStoreTransitionKeyType entry from the userInfo dictionary. It’s an NSNumber, enumerated to four keys. To test those with a switch statement I’m converting the NSNumber into an int.

Use this to check if an iCloud account has been changed, or if this is the first time an iCloud store has been started on the current device.

I’m explaining this as part of my screencast about using iCloud and Core Data:

iCloud in your iOS Apps – Part 4: iCloud and Core Data

In this part we’ll talk about how to make your Core Data powered app work with iCloud. This involves adding an option to your persistent store coordinator which will allow Core Data to write log files to iCloud. When changes are detected, the local Core Data store can merge them using those log files.

Here are the iCloud methods I added to the MasterViewController. First the observers under viewDidLoad:

And here are the event handler methods:

Demo Project

Here’s the demo project that I’m building. Don’t forget to change the Bundle ID and your Team ID to make it work on your devices:

Enjoy creating some rad iCloud apps 😉

Further Reading

Watch the whole series

Enjoy!

Watch the full course in one convenient playlist:
Catch this episode on my iOS Dev Diary Podcast:

iCloud in your iOS Apps – Part 3: Document Storage

In this part I’ll show you how to use your app’s ubiquitous folder to store arbitrary files in a user’s iCloud store. We’re not going to cover the UIDocument class here because it adds a layer of complexity to an already difficult subject, and for simple files it’s just not necessary. We’ll also cover how to download new files if iCloud changes have been detected.

There are two code snippets I’m referencing here: one is the method to retrieve your iCloud Documents folder (don’t forget to make it public like I did). This one goes into the AppDelegate.m:

I’m also talking about the NSMetadataQuery which will detect changes in your iCloud Documents folder. This is a custom initialiser so you’ll need to create a property for it. Here’s the initialiser – in the video I’m using it in my ViewController class:

To kick this into action you’ll also need to add an observer under viewDidLoad:

Watch the whole series

Enjoy!

Watch the full course in one convenient playlist:
Catch this episode on my iOS Dev Diary Podcast: