RubyCocoa es un marco macOS que proporciona un puente entre los lenguajes de programación Ruby y Objective-C , lo que permite al usuario manipular objetos Objective-C desde Ruby y viceversa. Permite escribir una aplicación Cocoa completamente en Ruby, así como escribir una aplicación que mezcla código Ruby y Objective-C. En 2008 se estaba desarrollando un proyecto de Apple llamado MacRuby para reemplazar RubyCocoa. Posteriormente, en 2012 se lanzó un derivado patentado llamado RubyMotion , disponible para iOS, macOS y Android.
Algunas aplicaciones útiles de RubyCocoa son la exploración de las características de un objeto Cocoa con irb de forma interactiva, la creación de prototipos de una aplicación Cocoa, la escritura de una aplicación Cocoa que combine las características de Ruby y Objective-C y el empaquetado de la GUI nativa de macOS para un script Ruby.
RubyCocoa es un software gratuito , publicado bajo la licencia Ruby y la LGPL .
Historia
RubyCocoa se inició en 2001 por Hisakuni Fujimoto cuando implementó un módulo de extensión Ruby para envolver la función NSObject y NSClassFromString. Más tarde se integró con Project Builder (que luego se convirtió en Xcode ). En 2002, el proyecto se registró en SourceForge y el equipo de desarrollo comenzó a crecer.
En 2006, un desarrollador de Apple , Laurent Sansonetti, se unió primero a la lista de confirmadores , y luego se realizó una presentación de RubyCocoa durante la WWDC . Apple declaró que RubyCocoa se incluirá y admitirá en Mac OS X v10.5 “Leopard”.
En agosto de 2008, Sansonetti confirmó que MacRuby " supuestamente reemplazará a RubyCocoa " en el futuro.
¿Cómo funciona el puente?
RubyCocoa a veces se interpreta como un conjunto de enlaces a los marcos de Cocoa, lo cual es falso. RubyCocoa es un puente real entre los lenguajes de programación Objective-C y Ruby.
Importación de clases perezosas
RubyCocoa importará las clases de Objective-C al mundo de Ruby bajo demanda. Por ejemplo, cuando acceda OSX::NSTableView
por primera vez en su código, RubyCocoa recuperará toda la información necesaria con respecto a esta clase del tiempo de ejecución de Objective-C y creará una clase Ruby del mismo nombre que actuará como un proxy. También importará de la misma forma todas las clases heredadas.
Reenvío de mensajes
Como se indicó anteriormente, RubyCocoa crea objetos proxy especiales. Cada vez que envía un mensaje de Ruby a un objeto proxy, RubyCocoa intentará reenviarlo a la instancia incrustada de Objective-C, traduciendo el nombre del mensaje a un selector de Objective-C y pidiendo al tiempo de ejecución de Objective-C que lo reenvíe.
Si se genera una excepción desde el mundo Objective-C, RubyCocoa la convertirá en una excepción de Ruby y se la enviará.
RubyCocoa utiliza el libffi biblioteca para llamar a los métodos de Objective-C implementaciones.
Anulación automática del método
RubyCocoa hace que sea fácil anular un método Objective-C de Ruby, ya sea en una subclase o directamente a la clase (como lo haría en Objective-C usando una categoría).
Una vez que se inserta su método, RubyCocoa recuperará la firma del método Objective-C existente e inyectará una nueva en el tiempo de ejecución de Objective-C, de la misma firma, pero que ahora apunta a su código.
Para lograr esto, utiliza el RubyCocoa libffi biblioteca para crear dinámicamente un cierre que llamará al método de Ruby, y apenas pasa un puntero a ese nuevo cierre al tiempo de ejecución de Objective-C.
Accediendo a los bits C
Debido a la naturaleza del lenguaje Objective-C, puede usar libremente C desde el código Objective-C. Para unir las partes C relevantes de un marco Objective-C, como estructuras, funciones, enumeraciones, constantes y más en C, RubyCocoa se basa en el proyecto BridgeSupport .
RubyCocoa interpretará en tiempo de ejecución los archivos BridgeSupport (utilizando el muy rápido xmlTextReader de libXML 2) y, en consecuencia, manejará su contenido. Por ejemplo, construirá las clases de proxy Ruby para las estructuras C y también creará las funciones.
Tenga en cuenta que las operaciones costosas, como la localización de los símbolos, se realizan a pedido y, obviamente, solo una vez.
Formatear cadenas
RubyCocoa puede detectar API que utilizan cadenas de formato, como NSLog o NSString.stringWithFormat, y convertir adecuadamente los argumentos de las variables a los tipos especificados en la cadena de formato.
Punteros de función
RubyCocoa le permite pasar Proc
objetos Ruby como argumentos de puntero de función. Luego usará la biblioteca libffi para crear dinámicamente un cierre y pasarlo a la función / método subyacente.
Creación de aplicaciones Cocoa escritas en Ruby
La instalación de RubyCocoa también instala automáticamente las plantillas Xcode correspondientes . Esto permite a los desarrolladores seleccionar "Aplicación Cocoa-Ruby" como el tipo de proyecto Xcode y Xcode generará todos los archivos necesarios para ellos.
Cómo llamar a métodos Objective-C desde Ruby
Para invocar un método Objective-C, reemplace cada dos puntos en el nombre del método, excepto el último, con un guión bajo. Así, por ejemplo, el método de instancia de NSWindow se initWithContentRect:styleMask:backing:defer:
convierte en initWithContentRect_styleMask_backing_defer
.
Todas las clases y funciones de Cocoa pertenecen al OSX
módulo, por ejemplo, el código Objective-C:
[[ NSWindow alloc ] initWithContentRect : frame styleMask : NSTitledWindowMask backing : NSBackingStoreBuffered diferir : NO ]
se convertirá:
OSX :: NSWindow . alloc . initWithContentRect_styleMask_backing_defer ( marco , OSX :: NSTitledWindowMask , OSX :: NSBackingStoreBuffered , falso )
Como puede ver, esto disminuye la legibilidad del código al hacer que los nombres de los parámetros de Objective-C sean inútiles. Entonces, hay otra forma conveniente de escribir las llamadas al objc_send
método : el método, que acepta símbolos Ruby como nombres de parámetros. Por ejemplo, el código anterior también se puede escribir como:
OSX :: NSWindow . alloc . objc_send ( : initWithContentRect , marco , : styleMask , OSX :: NSTitledWindowMask , : respaldo , OSX :: NSBackingStoreBuffered , : Defer , falsa )
Ventajas de RubyCocoa
- Como Ruby es un lenguaje interpretado, no es necesario volver a compilar la aplicación con frecuencia durante el desarrollo.
- Algunas de las funciones ricas de Ruby, como la compatibilidad con expresiones regulares incorporadas, hacen que escribir el código sea más rápido y también hacen de RubyCocoa una herramienta ideal para la creación de prototipos.
Desventajas
- Ignorando la velocidad del intérprete Ruby, las aplicaciones RubyCocoa siempre serán más lentas que las aplicaciones Objective-C / Cocoa debido a la sobrecarga adicional de conversión de objetos.
- Debido a que Ruby no es seguro para subprocesos, no es posible enviar varios subprocesos nativos para ejecutar el código RubyCocoa. Sin embargo, se pueden usar los hilos emulados de Ruby.