Guías
Tendencia

Marzipan, guía para probar nuestra app iOS como una app de Mac con el framework iOSMac

En la pasada WWDC Apple presentó algo que ya se nos había adelantado unos meses antes, y que es el primer paso de la universalidad de las apps en Apple: el denominado proyecto Marzipan.

Un poco de historia

Si hacemos un poco de historia, recordaremos que cuando Apple presentó en la MacWorld de 2007 el iPhone, Steve Jobs nos dijo que este nuevo teléfono móvil iba a cambiarlo todo y evolucionar el software bebé que existía hasta ese momento en los smartphones (que según sus palabras no eran tan smart como se decía). La forma de hacerlo es que el iPhone ejecutaba OS X. Esa era la clave. No tenía sentido reinventar algo cuando ya tienes todos los componentes en tu mano para dar lo que necesitas: Core Animation, la librería Cocoa en sí, Core Data, las librerías de red, de sonido, multitarea… por lo tanto, desde 2007 el entonces iPhone OS (luego renombrado como iOS en 2010) ya era una versión para arquitectura ARM del sistema operativo OS X.

Steve Jobs presenta el primer iPhone, cuyo corazón es OS X.
Steve Jobs presenta el primer iPhone, cuyo corazón es OS X.

Pero solo hay dos componentes que aún seguían sin tener compatibilidad con iOS: AppKit y Aqua. Aqua es el framework que da soporte al escritorio de OS X (ahora macOS) y AppKit es el que permite construir las apps para el Mac. Un framework cuya existencia se remonta al año 1988 con la salida de la primera versión del sistema operativo NeXTSTEP. Apple decidió, en vez de usar AppKit en el iPhone y Aqua crear lo que llamó SpringBoard (el escritorio que comparten iPhone y iPad, al menos hasta este año) y UIKit, un nuevo framework de construcción de apps que se adaptará a la nueva generación táctil de dispositivos.

Como ya sabemos UIKit nos permite usar interfaces como las tablas, colecciones, los diferentes elementos que construyen interfaces, páginas, scroll y mucho más. He introdujo formas de manejar las pantallas de forma táctil con gestos o el famoso scroll inercial que tanto sorprendió a propios y extraños en aquella época. Algo que todos los sistemas móviles táctiles presentados después han heredado en mayor o menor medida.

UIKit, el futuro, AppKit, el pasado

Han pasado más de 10 años desde que Apple presentara a los desarrolladores UIKit como framework, y aunque este no haya evolucionado especialmente en sus componentes, sí lo ha hecho en la forma en que es usado. En estos años hemos visto la introducción de los storyboards como forma de crear todo un flujo de navegación en un solo fichero con una serie de controles automáticos, el perfeccionamiento del diseño adaptativo, la llegada de Swift como elemento de cambio…

UIKit ha sido el framework elegido por Apple para crear la unificación a través del software de todos sus sistemas.

Ahora toca el siguiente gran cambio: el momento en que tener dos frameworks diferentes de construcción de interfaces no tiene sentido y tenemos que apostar por un ganador que será el que consiga hegemonizar todos los sistemas Apple. Y el elegido ha sido UIKit, el cual se ha adaptado para ser capaz de adaptarse al Mac, como ya lo hizo en su momento para adaptarse a watchOS o tvOS. El proyecto para que esto suceda es el citado, Marzipan.

Probando Marzipan

Marzipan es un framework privado en macOS Mojave 10.14. No podemos usarlo. De hecho, sus enlaces están prohibidos por el sistema por defecto. Como desarrolladores sabemos que las capacidades que tendrá una app (acceder a determinados servicios o componentes del sistema) dependen de un entitlement al que debemos registrarnos. Estos pueden ser públicos (los que normalmente usamos) o privados. Pues bien: el framework iOSMac donde está la versión de UIKit para Mac al ser privado requiere que nuestra app tenga un entitlement privado y que el certificado de firma de Apple lo valide. Cosa que como es obvio, nuestros certificados de desarrollador no hacen.

Presentación de Marzipan en la última WWDC 2018
Presentación de Marzipan en la última WWDC 2018

Ninguno de nuestros certificados de firma soportan la firma de componentes privados del sistema, por seguridad, así que por eso, no podremos ejecutar ninguna app que use este framework de una forma normal. Para poder hacerlo, tendremos que deshabilitar dos servicios del sistema: el CSR o protección de la integridad del sistema y el AMFI o la integridad de ficheros del sistema.

Ojo: estas modificaciones dejan el sistema más vulnerable a ataques de cualquier tipo de código malicioso o troyano, y no es recomendable que permanezcan como estado permanente del sistema.

Para hacer este cambio (bajo nuestra responsabilidad), debemos reiniciar el Mac en modo recuperación (iniciando con CMD+R) y una vez allí abrir el terminal y escribir estas dos líneas, una tras otra.

csrutil disable 
nvram boot-args="amfi_get_out_of_my_way=0x1"

Una vez ejecutado, podemos reiniciar y ya tendremos el sistema preparado para usar Marzipan. Para ello, bajaremos una utilidad libre creada por el desarrollador Steven Troughton-Smith llamada marzipanify, que nos permitirá convertir nuestra app. Podemos bajarla aquí. La abrimos, generamos y recogemos el binario que crea en la carpeta Products del proyecto.

Transformando la app

Abrimos la app en Xcode y deberemos revisarla. Es importante que entendamos que nada que no sea constraint será adaptado en tiempo real. Es decir: si tenemos una interfaz que se dibuja haciendo uso de algún tipo de tamaño de cálculo fijo, esto creará un elemento inalterable. Solo el uso de una interfaz adaptativa permitirá a nuestra app redimensionarse sola cuando la veamos en una ventana. También deberemos tener como target mínimo iOS 12 para que funcione.

Para poder crear la app con el framework Marzipan iOSMac, debemos tener el target de la app en iOS 12.

Adicionalmente hay una serie de frameworks y componentes de UIKit que no existen aún en la versión de iOSMac que vamos a usar, por lo que cualquier referencia a los mismos en nuestra app deberá de ser eliminada si queremos que funcione, entre los siguientes:

  • SafariServices.framework (SFSafariViewController no está portada porque no tiene sentido, en su lugar hay que usar openURL)
  • CoreTelephony.framework (CTTelephonyNetworkInfo especialmente)
  • Social.framework (SLComposeViewController)
  • MessageUI.framework (MFMailComposeViewController)
  • OpenGLES.framework (OpenGL ES está deprecado en Mac)
  • AddressBook.framework 

También hay algunas clases que no podremos usar y tendremos que deshabilitar para que no sean usadas:

  • UIImpactFeedbackGenerator (el Mac no puede generar una respuesta háptica, así que no está integrado)
  • UIPrintInfo (al no existir UIWebView, este control tampoco va)
  • [UIViewController setNeedsUpdateOfHomeIndicatorAutoHidden:](Es función específica de los iPhone con notch)
  • UIDocumentBrowser (El inspector de documentos en Mac no tiene sentido alguno)
  • PHCachingImageManager (cualquier uso de Photos.framework es un problema en sí porque no existe en Mac tal cual)

Una vez tengamos la app como queramos, la ejecutamos en un simulador, por ejemplo el del iPhone XR o de un iPad Pro. Una vez en pantalla, volvemos al Xcode y buscamos nuestra app bajo la carpeta Products donde encontraremos el .app. Botón derecho, Show in Finder e iremos a la carpeta donde está la app que se está ejecutando en ese momento en el simulador, el cual podemos dejar abierto.

Dicha carpeta, que pertenece a la estructura del propio simulador iOS, es donde vamos a trabajar. Cogemos el ejecutable de marzipanify y lo copiamos a esta carpeta, para luego abrir un terminal que apunte a ella. Una vez allí ejecutamos simplemente:

marzipanify "nombre de la app".app

Veremos que la app empieza a crear varios ficheros de entitlements para nuestra app, y lo que hará internamente será crearle todos los permisos y enlaces necesarios para que en vez de apuntar al framework UIKit de iOS que forma parte del simulador, enlazará al nuevo framework iOSMac que da soporte a Marzipan. Si nuestra app debe soportar un target anterior a iOS 12 deberemos anteceder a la llamada de marzipanify la instrucción INJECT_MARZIPAN_GLUE=1.

Terminado, si intentamos ejecutar la app desde el Finder veremos que nos dará un error y no se ejecutará. Si la intentamos arrancar desde el propio terminal nos dirá que ha tenido un error al enlazar al framework de reproducción de vídeo compilado con Swift o incluso fallos con el acceso al Bundle de archivos.

Esto es debido a que Swift no está autorizado a ser usado como librería con el framework privado iOSMac. Para arreglarlo debemos ir al fichero del sistema /System/iOSSupport/dyld/macOS-whitelist.txt y añadir al final nuestra propia app, con el objeto que el sistema le permita enlazar la versión de Swift con el framework privado sin problema. Hemos de añadir la ruta completa hasta el .app con que estamos trabajando y que hemos transformado.

Si todo ha ido bien, ejecutaremos y tendremos nuestra app en modo Marzipan delante nuestra para probarla. Si queremos ajustar cualquier cosa en la misma, tendremos que borrar el .app generado, así como todos los ficheros de entitlements que se han generado. Si no lo hacemos, tendremos un error de firma del código. Luego volvemos a ejecutar para que se regenere el .app y volvemos a repetir el paso de ejecutar marzipanify.

Como pequeño y obvio consejo: jugad con una copia de vuestro proyecto con que queráis probar.

El primer paso hacia la universalización

Sin duda, es una experiencia interesante y que nos puede permitir incluso empezar a preparar nuestra app si queremos que en septiembre de este año 2019, pueda ser publicada también en su versión en Mac. Así podemos ir adelantado trabajo.

Poco más, esperamos que nos contéis vuestra experiencia en los comentarios y no olvidéis suscribiros a la página, y seguirnos en nuestros podcasts en Cuonda, Apple Coding y Apple Coding Daily si queréis estar al día de todo lo relacionado con el desarrollo en entornos Apple con Swift. O seguirnos en nuestra canal de Youtube donde vamos a empezar a subir mucho contenido. Poco más, disfrutadlo, un saludo y Good Apple Coding.

El vídeo del podcast Apple Coding Daily donde hablamos de Marzipan


Etiquetas

Julio César Fernández

Analista, consultor y periodista tecnológico, desarrollador, empresario, productor audiovisual, actor de doblaje e ingeniero de vídeo y audio.

Artículos relacionados

También en

Cerrar
Botón volver arriba
Cerrar
Cerrar