i​OS 12

Si viste la Keynote de la WWDC de este año, estarás al tanto de todas las grandes novedades introducidas en iOS 12: Siri Shortcuts, ARKit 2 y Core ML 2. Sin mencionar el bombazo del gran anuncio del rumoreado puente iOS / Mac, con el nombre en clave «Marzipan».

Y si viste la sesión Platforms State of the Union de este año, estarás al corriente de nuevas tecnologías menos glamurosas pero igualmente de excitantes, como la UI personalizable de notificaciones y los nuevos frameworks Network y Natural Language.

Pero en NSHipster nos interesan los entresijos: los pequeños (y nos atrevemos a decir, oscuros) cambios que se añaden y generan un gran impacto en nuestro día a día.

Las release notes de iOS 12 y de Foundation cubren muchos de estos cambios. Sin embargo, no cuentan toda la historia. Para eso, tienes que cavar más hondo.

Para celebrar el lanzamiento de iOS 12, vamos a compartir unas cuantas perlas que encontramos escudriñando los diffs de las API de iOS 11.4 a iOS 12. Muchos están todavía sin documentar, así que procede con cautela.


Priorización del tráfico de las peticiones de red importantes

¿Conoces Fast Lane para iOS? No, no este fastlane. No, para este IOS, tampoco.

Fast Lane (¿o es Fastlane?) es un mecanismo usado para priorizar tráfico de red de acuerdo a su tipo (audio, video o datos en segundo plano). Es una tecnología específica de los routers Cisco (los cuales comprenden casi la mitad de todo el tráfico de internet), que encapsula varios estándares Wi-Fi: 802.11r para roaming rápido, 802.11k para roaming asistido y 802.11v para configuración remota.

Gracias a una colaboración entre Apple y Cisco anunciada en 2015, los desarrolladores iOS pueden optar a esta tecnología especificando el tipo de servicio (QoS) de las conexiones de red (aunque muchas de las APIs de alto nivel hacen esto por ti automáticamente).

En iOS 12, los objetos URLRequest pueden indicar el networkServiceType de NSURLNetworkServiceTypeResponsiveData para priorizar peticiones:

import Foundation

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

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

Esta opción no está documentada actualmente, pero el consejo de los ingenieros que presentaron la Sesión 714 de la WWDC 2018: “Optimizando tu App para el Internet actual” es usar esta herramienta con criterio, solo cuando el tiempo sea la clave. El ejemplo que usaron para la demo fue la pantalla de pago de una app de compras, pero puedes extrapolarlo a otros casos de uso.

Lectura de etiquetas NFC en segundo plano

Una de las preguntas más recurrentes de las WWDC de 2018 era acerca de la nueva propiedad ndefMessagePayload añadida a NSUserActivity. En aquel momento, lo máximo que los ingenieros de Apple decían durante las Lab sessions era un «sin comentarios».

Pero todo se aclaró con los anuncios de los iPhone XS, iPhone XS Max y iPhone XR de la semana pasada. Estos dispositivos son capaces de leer etiquetas NFC en segundo plano y, con iOS 12 podrás, entre otras cosas, lanzar apps, iniciar llamadas y abrir URLs como respuesta al escaneo de etiquetas NFC compatibles.

Sin configurar nada previamente.

Para evitar una activación involuntaria, solo funcionará si el iPhone está desbloqueado, con el Modo Avión desactivado y no se esté usando Apple Pay o la cámara en ese momento.

Con esta integración NFC, Apple espera cumplir las promesas que hizo sobre los iBeacons de BLE, allá por el año 2013; esta vez ofreciendo al mundo real una interfaz mucho más elegante que la depravación que supone escanear un código QR (una práctica extendida en China, pero muy ignorada en el resto del mundo).

Acercar tu teléfono a la placa del expositor de un museo para obtener información adicional es, quizá, el caso de uso más típico a la hora de promocionar las tecnologías de NFC y iBeacons.

Habilitar este tipo de funcionalidad en tu app requiere entitlements, definir dominios asociados y otras configuraciones, sin mencionar las APIs que tienes que implementar. Por suerte, Apple documentó este proceso, incluyendo este proyecto de ejemplo y este artículo.

Búsqueda de contactos por número de teléfono y dirección de email

El framework Contacts fue introducido en iOS 9 y macOS El Capitan como reemplazo del framework AddressBook.

Hasta hace poco, solo podias buscar contactos por nombre e identificador. Con iOS 12, puedes usar los métodos predicateForContacts(matching:) y predicateForContacts(matchingEmailAddress:) de la clase CNContact para construir predicados para buscar contactos por números de teléfono y direcciones de email.

Por ejemplo, para obtener el nombre y apellido de todos los contactos con un número de teléfono y dirección de email determinados, crea un CNContactFetchRequest, especifica un predicado compuesto AND creado por los subpredicados individuales, y pásalo como parámetro al método enumerateContacts(with:) del CNContactStore actual:

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
    // ...
}

Actualización de la ubicación durante el vuelo

Los iPads son especialmente populares entre pilotos, los cuales los usan para tareas de navegación y planificación del vuelo. Si estás trabajando en una app diseñada para gente que vuela en cabina, te encantará saber que CLLocationManager tiene algo para ti en iOS 12.

La propiedad activityType existe desde hace tiempo, pero sigue siendo una opción de configuración poco conocida de CLLocationManager. Si utilizas este manager para seguir los cambios de ubicación en el tiempo, una optimización fácil de hacer es especificar cómo esperas que los usuarios se muevan. Hasta ahora, estos modos de transporte han sido estrictamente terrestres: en automóvil, andando / corriendo / en bici, otros. Pero en iOS 12, ¡puedes especificar el tipo de actividad aérea y dejar que los algoritmos de seguimiento de tu aplicación se disparen!

import CoreLocation

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

Detección de orientación plana

¿Alguna vez has querido determinar si un dispositivo iOS está sobre una superficie plana, pero no querías hacer dos comparaciones de igualdad en el proceso? En iOS 12, hay una nueva propiedad para esto: isFlat.

import UIKit

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

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

Autocompletado de nuevas contraseñas y de códigos de un solo uso en campos de texto

Apple se esfuerza en hacer que la entrada de texto por parte del usuario sea lo más agradable posible. Pero a pesar de este esfuerzo, el hecho es el que es: la experiencia de teclear sobre un trozo de cristal palidece en comparación al hacerlo sobre un teclado físico (a pesar del descontento con los últimos modelos de MacBook).

Para minimizar la cantidad de texto a introducir, iOS 10 añadió la propiedad textContentType para controles que conformen el protocolo UITextInputTraits, como UITextField y UITextView. Con ello defines el valor semántico del control, lo que permite el autocompletado de nombres y direcciones en base a la información del usuario.

iOS 12 y tvOS 12 expanden esto añadiendo nuevos tipos de contenido: UITextContentTypeNewPassword y UITextContentTypeOneTimeCode.

Cuando indicas el tipo .newPassword junto con la propiedad passwordRules, Password AutoFill puede generar nuevas contraseñas automáticamente de acuerdo a los requerimientos de autenticación del sistema.

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

Cuando indicas el tipo .oneTimeCode, el campo de texto puede autocompletar los códigos de autenticación de dos factores recibidos por SMS.

textField.textContentType = .oneTimeCode

Y con esto terminamos esta ronda espeleología por los diffs de iOS 12. Como se trata de una release gigantesca, intentaremos cubrir muchas más APIs nuevas en profundidad durante las próximas semanas.

¿Tienes alguna sugerencia sobre lo que deberíamos cubrir a continuación? ¡Escríbenos en Twitter!

Artículo siguiente

No todo el código puede ser glamuroso. De hecho, mucha de la infraestructura de bajo nivel que hace que todo funcione es, a veces, un amasijo repetitivo.