Codementor Events

How to Build Universal iOS Applications

Published Jan 24, 2019
How to Build Universal iOS Applications

Learn how to build universal iOS applications in this guest post by Donny Wals, a passionate iOS developer with several years of experience.

It is not uncommon for people to own more than one iOS device. A lot of people who own an iPhone are likely to have an iPad lying around somewhere as well. Users who own multiple devices expect their apps to work well on any screen they have nearby. Ever since Apple launched the iPad, it has encouraged developers to make their apps universal to make sure they run on both the iPhone and the iPad.

A lot has changed since then. Currently, there are more screen sizes to keep in mind than ever before, and the tools that you have at your disposal to make beautiful layouts have gotten better and better over the years. You can use a single storyboard file to set up your layout for any screen size that is available to users. The best part is that you don't have to start from scratch setting up your layout for every screen size. You can use a single layout and tweak it as needed for certain screen sizes.

> Note
If you don't make your apps adaptive, your users will have a sub-par experience when they view your app on a different device. Imagine having designed your app for the iPhone SE form factor, but one of your users runs it on a 12.9" iPad Pro. You can probably imagine how terrible your layout would look.

Users tend to love apps that work on any device they own, and if you don't make your app compatible with iPad while having developed it for an iPhone, then Apple will make it available on iPads anyway. Your app will run in a scaled-up fake iPhone resolution that looks awful. It typically only takes a small effort to make your app work well on an iPad, and the rewards are great. To make your app look great on all screen sizes, you use size classes.

A size class is a property that belongs to the UITraitCollection class. A trait collection describes the features that make up the environment in which a certain view controller exists. Some of these traits describe the available screen space. But they also tell you whether a screen supports a wide color gamut or whether force touch capabilities are present. For now, you'll focus on size classes. At the time of writing, two size classes exist: regular and compact. The following list shows several available device form factors and their corresponding size classes in all orientations:
• Plus-sized iPhones, iPhone X(s) and iPhone Xs max:
• Portrait orientation: compact width x regular height
• Landscape orientation: regular width x compact height
• All other iPhones:
• Portrait orientation: compact width x regular height
• Landscape orientation: compact width x compact height
• All iPad sizes:
• Portrait orientation: regular width x regular height
• Landscape orientation: regular width x regular height

The preceding list is not entirely exhaustive for all possible size class combinations. On the iPad, an app can appear in multitasking view, potentially giving it a compact width size class.

> Note
You should not use size classes as an indicator for the device the user is holding. An iPad could look very similar to an iPhone if you base your assumptions on the size class. Typically, this is good: you should optimize your app for capabilities, not a specific device. However, if you need to know what type of device the user is holding, you can use userInterfaceIdiom on UITraitCollection to find out the name of the current device.

Whenever you create a new project in Xcode, the app is configured to be universal by default. This means that your app will work on all devices and when you publish your app to the App Store, it will be natively available on the iPad and iPhone. If you need to change this setting, you can do so in your project settings by changing the Devices option from Universal to something else, for instance, iPhone. The following screenshot shows this option in the project settings window:

1.png

Typically, you will prefer to build your app universally, but sometimes you want to target a single device. Be aware that selecting iPhone does not make it impossible for your app to run on an iPad. Your users can download the iPhone version of your app on their iPad, and the iPad will then render the app in a scaled window. The following screenshot shows how this would look for the Hello-Contacts app:

2.png

In addition to selecting the type of devices your app runs on, you can also configure the device orientations that are supported by your app. If your app is universal and you wish to make it compatible with iPad multitasking, the iPad version of your app must support all orientations. Unless you absolutely have to stick to a certain orientation on the iPad, it is typically recommended to support any screen orientation in your app.

On the iPhone, it is typical for apps to only work in portrait mode. This is okay, and you can support the landscape orientation whenever it fits your app. The only orientation that is a little bit strange to support on an iPhone is upside down. It is typically discouraged to support this orientation in an iPhone app.

A single app can support different screen orientations for iPhone and iPad. This allows you to make an app portrait only on iPhone and support any orientation on iPad. By default, Xcode sets up your project so that it supports all iPad orientations, and only the ones you check in your project settings are supported for the iPhone. Open your Info.plist file to see the general and iPad-specific orientation configurations under the Supported interface orientations keys. If you change the configuration in your project settings, your Info.plist will update as well.

Remember that you implemented some code to add support for showing your action sheet on the iPad? Go ahead and run Hello-Contacts on an iPad simulator and long-press on one of the contacts to see the delete popover appear. The popover should be presented as shown in the following screenshot:

3.png

You'll notice that the popover isn't presented in the best position. Users will likely expect to see the popover appear alongside the contact image instead of seeing positioned entirely over the contact cell. The current implementation for showing the popover looks like this:

if let popOver = confirmationDialog.popoverPresentationController {
  popOver.sourceView = tappedCell
}

The preceding code sets a sourceView property on the popover. The popover uses the sourceView property as a container for the popover window. This means that the popover is added as a subview of the sourceView property.

In addition to setting the sourceView property, you can also provide the popover with a sourceRect property. The sourceRectproperty specifies an area in which the popover will be anchored. The coordinates for this area are relative to the sourceView property. Update the popover presentation code with the following implementation to position the popover nicely alongside the contact image view:

if let popOver = confirmationDialog.popoverPresentationController {
  popOver.sourceView = tappedCell

  if let cell = tappedCell as? ContactCollectionViewCell {
    let imageCenter = cell.contactImage.center
    popOver.sourceRect = CGRect(x: imageCenter.x,  y: imageCenter.y,
                                width: 0,  height: 0)
  }
}

Even though this update isn't crazy complex, it is a piece of adaptive code that optimizes the way your app looks in a certain scenario. By checking whether a popoverPresentationController exists, you learn something about the environment that your app runs in.

Since this property is only available on specific devices in specific conditions, you want to configure the popover only when it makes sense. The beauty of truly adaptive code is that it makes no assumptions. It simply reads the facts and acts upon that. If Apple would release a new device that also shows a popover, your code would already be able to handle it!

It has already been mentioned, but it's critical to check the right properties of your environment when building apps that should look great everywhere. If you are doing something that is specific to a device, especially an iPad, it is time to step back and reconsider.

The available screen real estate for your app on an iPad can be extremely narrow and tall if the user holds their iPad in portrait and uses multitasking. The more flexible you make your code and the fewer assumptions you make, the better your apps will adapt to their environment.

If you have never seen an app running in multitasking mode on an iPad, now is the time to build and run your app on an iPad simulator. When the app is running, swipe up from the bottom of the screen to reveal the Dock and drag an app from the dock upwards, so it appears next to the Hello-Contacts app.
You can resize each app by dragging the spacer in the middle of the screen and rotate the device. The app layout will always adapt to the available space because the entire app was set up with adaptivity in mind.

That’s it! If you enjoyed reading this article and want to learn more about building awesome iOS apps, you must explore Mastering iOS 12 Programming – Third Edition. Written by Donny Wals and expert in iOS app development, Mastering iOS 12 Programming – Third Edition takes a no-frills approach, focusing on teaching advanced concepts through a series of small projects and standalone examples that help you gain expertise with various aspects of iOS application development.

Discover and read more posts from PACKT
get started