i​OS 12

Written by Mattt

If you tuned in to this year’s WWDC Keynote, you’ll know all about the big features in iOS 12: Siri Shortcuts, ARKit 2, and Core ML 2 — not to mentioned the bombshell pre-announcement of the long-rumored iOS / Mac bridge, codenamed “Marzipan”.

And if you watched this year’s Platforms State of the Union session, you’ll be aware of the less glamorous, but equally exciting new technologies, like customizable user notification UI, and the new Network and Natural Language frameworks.

But here at NSHipster, we’re interested in the nitty-gritty: the small (dare we say, obscure?) changes that add up to make a big impact to our day-to-day. This year’s iOS 12 release notes and Foundation Release Notes cover many of these changes, however they don’t tell the whole story. For that, you have to dig deeper.

In celebration of this week’s release of iOS 12, we’re sharing what we found after trawling through the API diffs from iOS 11.4 to 12. (As it were, many of these are still undocumented, so proceed with caution).


Prioritizing Network Traffic for Important Requests

Have you heard of Fast Lane for iOS? No, not that fastlane. No, not that IOS, either.

Fast Lane (or is it Fastlane?) is a mechanism used to prioritize wireless traffic according to its type, such as audio, video, or background data. It’s a technology specific to Cisco routers, (which account for about half of all internet traffic), that encapsulates several Wi-Fi standards like 802.11r for fast roaming, 802.11k for assisted roaming, and 802.11v for wireless configuration.

Thanks to a partnership between Apple and Cisco announced in 2015, iOS developers can opt-in to this technology by providing a service type (QoS marking) to network connections (though many high-level APIs take care of this for you automatically).

New in iOS 12, URLRequest objects can now set networkServiceType to NSURLNetworkServiceTypeResponsiveData to prioritize time-sensitive requests:

import Foundation

let url = URL(string: "https://example.com/checkout")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.networkServiceType = .responsiveData // Prioritize

URLSession.shared.dataTask(with: request) {
    (data, response, error) in
    // ...
}

This option is currently undocumented, but the guidance from the engineers presenting WWDC 2018 Session 714: “Optimizing Your App for Today’s Internet” is to use this feature judiciously, only when time is of the essence. The example they provide is “the checkout page for a shopping app”, but you can extrapolate other potential use cases.

Reading NFC Tags in the Background

One of the longstanding questions coming out of WWDC 2018 was the new ndefMessagePayload property added to NSUserActivity. At the time, the most that Apple engineers would offer during Lab sessions was “no comment”.

But all became clear with last week’s announcements of the iPhone XS, iPhone XS Max and iPhone XR. These devices support reading NFC tags in the background, and if you’re running iOS 12 on the latest generation of devices, you’ll be able to — among other things — launch apps, start calls, and open URLs in response to scanning compatible NFC tags. No additional setup required. To avoid inadvertent activation, this only works if the iPhone is unlocked and not currently in Airplane Mode or being used for Apple Pay or camera.

With this NFC integration, Apple hopes to fully realize past promises made about BLE iBeacons back in 2013, offering a sleeker interface to the real world than the depravity of scanning a QR code (a practice ubiquitous in China, but largely ignored to the rest of the world).

Perhaps the most commonly advertised use cases for both technologies NFC and iBeacon technologies have been visiting a museum and getting additional details about an exhibit by hovering your phone near a strategically-placed information placard.

Enabling this kind of functionality in your app requires entitlements, setting associated domains, and other configuration — not to mention the actual APIs you need to implement. Fortunately, Apple provides some extensive documentation for this process, including this sample code project and this article.

Matching Contacts on Phone Number and Email Address

The Contacts framework was introduced in iOS 9 and macOS El Capitan as a modern replacement for the AddressBook framework.

Until recently, you could only search for contacts by name and identifier. With iOS 12, you can now use the predicateForContacts(matching:), and predicateForContacts(matchingEmailAddress:) class methods on CNContact to construct predicates for matching on phone numbers and email addresses.

For example, if we wanted to retrieve the given and family name components for all contacts with a given phone number and email address, you create a CNContactFetchRequest, specify a compound “AND” predicate created from the individual subpredicates, and pass that to the enumerateContacts(with:) method called on the current CNContactStore:

import Contacts

let phoneNumber = CNPhoneNumber(stringValue: "+1 555 555 1234")
let phoneNumberPredicate = CNContact.predicateForContacts(matching: phoneNumber)

let emailPredicate = CNContact.predicateForContacts(matchingEmailAddress: "johnny@example.com")

var fetchRequest = CNContactFetchRequest(keysToFetch: [
    CNContactGivenNameKey as CNKeyDescriptor,
    CNContactFamilyNameKey as CNKeyDescriptor
])

fetchRequest.predicate =
  NSCompoundPredicate(andPredicateWithSubpredicates: [
    phoneNumberPredicate,
    emailPredicate
])

let store = CNContactStore()
try store.enumerateContacts(with: fetchRequest) { (contact, _) in
    // ...
}

Updating Location While Airborne

iPads are especially popular among pilots, who use them for navigation and flight planning. If you’re working on an app geared for folks up in the cockpit, you’ll be delighted to hear that CLLocationManager now has something just for you in iOS 12.

The activityType property has been around for a while, but remains a lesser-known configuration option for CLLocationManager. If you use a location manager to track changes in position over time, a quick “low-hanging fruit” optimization is to specify how you expect users to be perambulating. Until now, these modes of transportation have been strictly terrestrial: automotive, walking / running / biking, what have you. But in iOS 12, you can specify the airborne activity type and let your app’s motion tracking algorithms soar!

import CoreLocation

let manager = CLLocationManager()
manager.activityType = .airborne // ✈️

Detecting Flat Device Orientation

Have you ever wanted to determine whether an iOS device was laying flat on a surface, but were loath to do two equality checks in the process? Good news! In iOS 12, there’s a new convenience property: isFlat.

import UIKit

// iOS 12+
UIDevice.current.orientation.isFlat

// iOS <= 11.4
UIDevice.current.orientation == .faceUp ||
  UIDevice.current.orientation == .faceDown

Auto-filling New Passwords and One-Time Codes in Text Fields

Apple goes to heroic lengths to make user input pleasant on iOS devices. Yet despite their best efforts, the fact remains: the experience of typing on a featureless piece of smooth glass is always going to pale in comparison to a proper hardware keyboard (discontentment about the latest MacBook models notwithstanding).

To minimize the amount of text-entry drudgery, iOS 10 introduced the textContentType property for controls conforming to the UITextInputTraits protocol — namely UITextField and UITextView. By providing one of the enumeration values you declare the semantic value of the control, which allows for details like certain name and address components to be auto-filled based on the current user’s information.

iOS 12 and tvOS 12 expand on this by adding two new content types: UITextContentTypeNewPassword and UITextContentTypeOneTimeCode.

When you specify the .newPassword content type in conjunction with the passwordRules property , Password AutoFill can automatically generate new passwords according to the login requirements of the system.

textField.textContentType = .newPassword
textField.passwordRules = .init(descriptor:
    "allowed: ascii-printable; minlength: 8;"
)

When you specify the .oneTimeCode content type, the text field can automatically forward two-factor authentication codes received via SMS.

textField.textContentType = .oneTimeCode

That wraps up this round of iOS 12 diff spelunking. Of course, this is an enormous release, so we look forward to cover many more new APIs in greater depth in the weeks to come.

Do you have any suggestions about what we should cover next? Please get in touch via Twitter!

NSMutableHipster

Questions? Corrections? Issues and pull requests are always welcome — NSHipster is made better by readers like you.

This article uses Swift version 4.2. Find status information for all articles on the status page.

Next Article

With the design refresh of iOS in its 7th release, skeuomorphic design was famously sunset. In its place, a new paradigm emerged, in which UI controls were made to feel like physical objects rather than simply look like them.