stringtranslate.com

C objetivo

Objective-C es un lenguaje de programación orientado a objetos de alto nivel , de propósito general , que agrega mensajería estilo Smalltalk al lenguaje de programación C [3] . Desarrollado originalmente por Brad Cox y Tom Love a principios de la década de 1980, NeXT lo seleccionó para su sistema operativo NeXTSTEP . Debido al linaje directo de Apple macOS de NeXTSTEP, [4] Objective-C fue el lenguaje de programación estándar utilizado, respaldado y promovido por Apple para desarrollar aplicaciones macOS e iOS (a través de sus respectivas API , Cocoa y Cocoa Touch ) hasta la introducción. del lenguaje de programación Swift en 2014. [3]

Los programas Objective-C desarrollados para sistemas operativos que no son de Apple o que no dependen de las API de Apple también pueden compilarse para cualquier plataforma compatible con GNU GCC o LLVM / Clang .

Los archivos de programa de 'mensajería/implementación' del código fuente de Objective-C generalmente tienen extensiones de nombre de archivo .m , mientras que los archivos de 'encabezado/interfaz' de Objective-C tienen extensiones .h , al igual que los archivos de encabezado C. Los archivos Objective-C++ se indican con una extensión de archivo .mm .

Historia

Objective-C fue creado principalmente por Brad Cox y Tom Love a principios de la década de 1980 en su empresa Productivity Products International (PPI) . [5]

Antes de la creación de su empresa, ambos conocieron Smalltalk mientras estaban en el Centro de Tecnología de Programación de ITT Corporation en 1981. Los primeros trabajos sobre Objective-C se remontan a esa época. [6] Cox estaba intrigado por los problemas de la verdadera reutilización en el diseño y programación de software . Se dio cuenta de que un lenguaje como Smalltalk sería invaluable en la creación de entornos de desarrollo para desarrolladores de sistemas en ITT. Sin embargo, él y Tom Love también reconocieron que la compatibilidad con versiones anteriores de C era de vital importancia en el entorno de ingeniería de telecomunicaciones de ITT. [7]

Cox comenzó a escribir un preprocesador para C para agregar algunas de las capacidades de Smalltalk . Pronto tuvo una implementación funcional de una extensión orientada a objetos del lenguaje C , a la que llamó "OOPC" (Precompilador orientado a objetos). [8] Love fue contratado por Schlumberger Research en 1982 y tuvo la oportunidad de adquirir la primera copia comercial de Smalltalk-80, lo que influyó aún más en el desarrollo de su creación. Para demostrar que se podía lograr un progreso real, Cox demostró que para fabricar componentes de software intercambiables en realidad sólo se necesitaban algunos cambios prácticos en las herramientas existentes. Específicamente, necesitaban admitir objetos de una manera flexible, venir con un conjunto utilizable de bibliotecas y permitir que el código (y cualquier recurso que el código necesita) se agrupara en un formato multiplataforma.

Love y Cox finalmente formaron PPI para comercializar su producto, que combinaba un compilador Objective-C con bibliotecas de clases. En 1986, Cox publicó la descripción principal de Objective-C en su forma original en el libro Programación orientada a objetos, un enfoque evolutivo . Aunque tuvo cuidado de señalar que el problema de la reutilización implica mucho más que lo que proporciona Objective-C, el lenguaje a menudo se compara característica por característica con otros lenguajes.

Popularización a través de NeXT

En 1988, NeXT obtuvo la licencia de Objective-C de StepStone (el nuevo nombre de PPI, el propietario de la marca Objective-C) y amplió el compilador GCC para admitir Objective-C. NeXT desarrolló las bibliotecas AppKit y Foundation Kit en las que se basaron la interfaz de usuario NeXTSTEP y el Interface Builder. Si bien las estaciones de trabajo NeXT no lograron tener un gran impacto en el mercado, las herramientas fueron ampliamente elogiadas en la industria. Esto llevó a NeXT a abandonar la producción de hardware y centrarse en herramientas de software, vendiendo NeXTSTEP (y OPENSTEP) como una plataforma para programación personalizada.

Para eludir los términos de la GPL , NeXT originalmente tenía la intención de enviar la interfaz Objective-C por separado, permitiendo al usuario vincularla con GCC para producir el compilador ejecutable. Aunque inicialmente fue aceptado por Richard M. Stallman , este plan fue rechazado después de que Stallman consultara con los abogados de GNU y NeXT aceptara hacer de Objective-C parte de GCC. [9]

El trabajo para ampliar GCC estuvo dirigido por Steve Naroff, quien se unió a NeXT procedente de StepStone. Los cambios del compilador estuvieron disponibles según los términos de la licencia GPL , pero las bibliotecas en tiempo de ejecución no, lo que hizo que la contribución de código abierto fuera inutilizable para el público en general. Esto llevó a que otras partes desarrollaran dichas bibliotecas en tiempo de ejecución bajo licencias de código abierto. Más tarde, Steve Naroff también fue colaborador principal para trabajar en Apple para construir la interfaz Objective-C para Clang .

El proyecto GNU comenzó a trabajar en su implementación de software libre de Cocoa , denominada GNUstep , basada en el estándar OpenStep . [10] Dennis Glatting escribió el primer tiempo de ejecución de GNU Objective-C en 1992. El tiempo de ejecución de GNU Objective-C, que ha estado en uso desde 1993, es el desarrollado por Kresten Krab Thorup cuando era un estudiante universitario en Dinamarca . [ cita necesaria ] Thorup también trabajó en NeXT de 1993 a 1996. [11]

Desarrollo de Apple y Swift

Después de adquirir NeXT en 1996, Apple Computer utilizó OpenStep en su entonces nuevo sistema operativo, Mac OS X. Esto incluía Objective-C, la herramienta de desarrollo basada en Objective-C de NeXT, Project Builder , y su herramienta de diseño de interfaz, Interface Builder . Posteriormente, ambos se fusionaron en una sola aplicación, Xcode . La mayor parte de la API Cocoa actual de Apple se basa en objetos de interfaz OpenStep y es el entorno Objective-C más importante que se utiliza para el desarrollo activo.

En la WWDC 2014, Apple presentó un nuevo lenguaje, Swift , que se caracterizó como "Objective-C sin C".

Sintaxis

Objective-C es una capa delgada sobre C y es un " superconjunto estricto " de C, lo que significa que es posible compilar cualquier programa en C con un compilador de Objective-C e incluir libremente código en lenguaje C dentro de una clase de Objective-C. [12] [13] [14] [15] [16] [17]

Objective-C deriva su sintaxis de objeto de Smalltalk . Toda la sintaxis para operaciones no orientadas a objetos (incluidas variables primitivas, preprocesamiento, expresiones, declaraciones de funciones y llamadas a funciones) son idénticas a las de C, mientras que la sintaxis para funciones orientadas a objetos es una implementación de Smalltalk- Mensajería de estilo.

Mensajes

El modelo Objective-C de programación orientada a objetos se basa en el paso de mensajes a instancias de objetos. En Objective-C no se llama a un método ; uno envía un mensaje . Esto es diferente al modelo de programación estilo Simula utilizado por C++ . La diferencia entre estos dos conceptos está en cómo se ejecuta el código al que hace referencia el método o nombre del mensaje. En un lenguaje de estilo Simula, el compilador vincula el nombre del método a una sección de código en la clase de destino en la mayoría de los casos. En Smalltalk y Objective-C, el destino de un mensaje se resuelve en tiempo de ejecución y el propio objeto receptor interpreta el mensaje. Un método se identifica mediante un selector o SEL (un identificador único para cada nombre de mensaje, a menudo solo una cadena terminada en NUL que representa su nombre) y se resuelve en un puntero de método C que lo implementa: un IMP. [18] Una consecuencia de esto es que el sistema de paso de mensajes no tiene verificación de tipo. No se garantiza que el objeto al que se dirige el mensaje (el receptor ) responda a un mensaje y, si no lo hace, genera una excepción. [19]

Enviar el método de mensaje al objeto señalado por el puntero obj requeriría el siguiente código en C++ :

obj -> método ( argumento );

En Objective-C, esto se escribe de la siguiente manera:

[ método obj : argumento ]; 

El compilador traduce la llamada al "método" a la familia de funciones de tiempo de ejecución objc_msgSend(id self, SEL op, ...) . Diferentes implementaciones manejan adiciones modernas como super . [20] En las familias GNU, esta función se denomina objc_msg_sendv , pero ha quedado obsoleta en favor de un sistema de búsqueda moderno bajo objc_msg_lookup . [21]

Ambos estilos de programación tienen múltiples fortalezas y debilidades. La programación orientada a objetos en el estilo Simula ( C++ ) permite la herencia múltiple y una ejecución más rápida mediante el uso de enlace en tiempo de compilación siempre que sea posible, pero no admite el enlace dinámico de forma predeterminada. También obliga a todos los métodos a tener una implementación correspondiente a menos que sean abstractos . La programación estilo Smalltalk tal como se usa en Objective-C permite que los mensajes no se implementen, con el método resuelto para su implementación en tiempo de ejecución. Por ejemplo, se puede enviar un mensaje a una colección de objetos, a los que se espera que respondan sólo algunos, sin temor a producir errores de tiempo de ejecución. El paso de mensajes tampoco requiere que se defina un objeto en el momento de la compilación. Aún se requiere una implementación para que se llame al método en el objeto derivado. (Consulte la sección de escritura dinámica a continuación para conocer más ventajas de la vinculación dinámica (tardía).)

Interfaces e implementaciones

Objective-C requiere que la interfaz y la implementación de una clase estén en bloques de código declarados por separado. Por convención, los desarrolladores colocan la interfaz en un archivo de encabezado y la implementación en un archivo de código. Los archivos de encabezado, normalmente con el sufijo .h, son similares a los archivos de encabezado C, mientras que los archivos de implementación (método), normalmente con el sufijo .m, pueden ser muy similares a los archivos de código C.

Interfaz

Esto es análogo a las declaraciones de clases utilizadas en otros lenguajes orientados a objetos, como C++ o Python.

La interfaz de una clase normalmente se define en un archivo de encabezado. Una convención común es nombrar el archivo de encabezado según el nombre de la clase; por ejemplo, Ball.h contendría la interfaz de la clase Ball .

Una declaración de interfaz toma la forma:

@interface  nombre de clase  : nombre de superclase  { // variables de instancia } + método de clase1 ; + ( tipo_retorno ) métodoclase2 ; + ( tipo_retorno ) métodoclase3: ( tipo_param1 ) nombre_var_param1 ;    -  ( tipo_retorno ) método_instancia1con1parámetro: ( tipo_param1 ) nombre_var_param1 ; -  ( tipo_retorno ) método2con2parámetros de instancia: ( tipo_param1 ) nombre_var_param1 nombre_llamada_param : (tipo_param2 ) nombre_var_param2 ; @fin 

En lo anterior, los signos más indican métodos de clase , o métodos que se pueden invocar en la clase misma (no en una instancia), y los signos menos denotan métodos de instancia , que solo se pueden invocar en una instancia particular de la clase. Los métodos de clase tampoco tienen acceso a variables de instancia .

El código anterior es aproximadamente equivalente a la siguiente interfaz C++ :

clase nombre de clase : nombre de superclase pública { protegido : // variables de instancia      public : // Funciones de clase (estáticas) static void * classMethod1 (); tipo de retorno estático classMethod2 (); método de clase de tipo de retorno estático3 ( param1_type param1_varName );            // Funciones de instancia (miembro) tipo_retorno método_instancia1con1parámetro ( param1_tipo param1_varName ); return_type método de instancia2With2Parameters ( param1_type param1_varName , param2_type param2_varName = predeterminado ); };          

Tenga en cuenta que instanciaMethod2With2Parameters:param2_callName: demuestra el entrelazado de segmentos de selector con expresiones de argumentos, para las cuales no existe un equivalente directo en C/C++.

Los tipos de retorno pueden ser cualquier tipo estándar de C , un puntero a un objeto Objective-C genérico, un puntero a un tipo específico de objeto como NSArray *, NSImage * o NSString *, o un puntero a la clase a la que pertenece el método. (tipo de instancia). El tipo de retorno predeterminado es el ID de tipo genérico de Objective-C .

Los argumentos del método comienzan con un nombre que etiqueta el argumento que forma parte del nombre del método, seguido de dos puntos seguido del tipo de argumento esperado entre paréntesis y el nombre del argumento. La etiqueta se puede omitir.

-  ( void ) setRangeStart: ( int ) inicio fin: ( int ) fin ; - ( void ) importDocumentWithName: ( NSString * ) nombre conSpecifiedPreferences : ( Preferences * ) prefs beforePage : ( int ) insertPage ;      

Un derivado de la definición de interfaz es la categoría , que permite agregar métodos a clases existentes. [22]

Implementación

La interfaz sólo declara la interfaz de clase y no los métodos en sí: el código real está escrito en el archivo de implementación. Los archivos de implementación (método) normalmente tienen la extensión de archivo .m, que originalmente significaba "mensajes". [23]

@implementation  nombre de clase +  ( tipo_retorno ) métodoclase { // implementación } - ( tipo_retorno ) método_instancia { // implementación } @end     

Los métodos se escriben utilizando sus declaraciones de interfaz. Comparando Objective-C y C:

-  ( int ) método: ( int ) i { retorno [ self raíz_cuadrada : i ]; }    
int function ( int i ) { return raíz_cuadrada ( i ); }     

La sintaxis permite pseudonombrar argumentos .

-  ( void ) changeColorToRed: ( float ) rojo verde: ( float ) verde azul: ( float ) blue { //... Implementación... }    // Llamado así: [ myColor changeColorToRed : 5.0 green : 2.0 blue : 6.0 ];   

Las representaciones internas de un método varían entre las diferentes implementaciones de Objective-C. Si myColor es de la clase Color , el método de instancia -changeColorToRed:green:blue: podría tener la etiqueta interna _i_Color_changeColorToRed_green_blue . La i es para referirse a un método de instancia, con los nombres de la clase y luego del método agregados y los dos puntos cambiados a guiones bajos. Como el orden de los parámetros es parte del nombre del método, no se puede cambiar para adaptarlo al estilo o expresión de codificación como ocurre con los parámetros con nombre verdadero.

Sin embargo, los nombres internos de la función rara vez se utilizan directamente. Generalmente, los mensajes se convierten en llamadas a funciones definidas en la biblioteca de tiempo de ejecución de Objective-C. No necesariamente se sabe en el momento del enlace qué método se llamará porque la clase del receptor (el objeto al que se envía el mensaje) no necesita conocerse hasta el tiempo de ejecución.

Creación de instancias

Una vez que se escribe una clase Objective-C, se puede crear una instancia de ella. Esto se hace asignando primero una instancia no inicializada de la clase (un objeto) y luego inicializándola. Un objeto no es completamente funcional hasta que se hayan completado ambos pasos. Estos pasos deben realizarse con una línea de código para que nunca haya un objeto asignado que no haya sido inicializado (y porque no es prudente mantener el resultado intermedio ya que -initpuede devolver un objeto diferente al que se llama).

Creación de instancias con el inicializador predeterminado sin parámetros:

MiObjeto * foo = [[ MiObjeto alloc ] init ];     

Creación de instancias con un inicializador personalizado:

MiObjeto * foo = [[ MiObjeto alloc ] initWithString : miCadena ];     

En el caso de que no se realice una inicialización personalizada, a menudo se puede utilizar el método "nuevo" en lugar de los mensajes alloc-init:

MiObjeto * foo = [ MiObjeto nuevo ];    

Además, algunas clases implementan inicializadores de métodos de clase. Me gusta +new, combinan +allocy -init, pero a diferencia de +new, devuelven una instancia publicada automáticamente. Algunos inicializadores de métodos de clase toman parámetros:

MiObjeto * foo = [ MiObjeto objeto ]; MiObjeto * bar = [ MiObjeto objetoConCadena : @"Wikipedia :)" ];        

El mensaje alloc asigna suficiente memoria para contener todas las variables de instancia de un objeto, establece todas las variables de instancia en valores cero y convierte la memoria en una instancia de la clase; en ningún momento durante la inicialización la memoria es una instancia de la superclase.

El mensaje de inicio realiza la configuración de la instancia tras su creación. El método init suele escribirse de la siguiente manera:

-  ( identificación ) inicio {  self = [ superinicio ] ;    si ( yo ) {   // realiza la inicialización del objeto aquí } regresar a uno mismo ; }

En el ejemplo anterior, observe el idtipo de devolución. Este tipo significa "puntero a cualquier objeto" en Objective-C (consulte la sección Escritura dinámica).

El patrón inicializador se utiliza para garantizar que el objeto sea inicializado correctamente por su superclase antes de que el método init realice su inicialización. Realiza las siguientes acciones:

Un puntero de objeto no válido tiene el valor nil ; Las declaraciones condicionales como "if" tratan a nil como un puntero nulo, por lo que el código de inicialización no se ejecutará si [super init]se devuelve nil. Si hay un error en la inicialización, el método init debe realizar cualquier limpieza necesaria, incluido enviarse un mensaje de "liberación" y devolver nil para indicar que la inicialización falló. Cualquier verificación de dichos errores solo debe realizarse después de haber llamado a la inicialización de la superclase para garantizar que la destrucción del objeto se realizará correctamente.

Si una clase tiene más de un método de inicialización, sólo uno de ellos (el "inicializador designado") necesita seguir este patrón; otros deberían llamar al inicializador designado en lugar del inicializador de superclase.

Protocolos

En otros lenguajes de programación, estas se denominan "interfaces".

Objective-C se amplió en NeXT para introducir el concepto de herencia múltiple de especificación, pero no de implementación, mediante la introducción de protocolos . Este es un patrón que se puede lograr como una clase base abstracta de herencia múltiple en C++ o como una "interfaz" (como en Java y C# ). Objective-C utiliza protocolos ad hoc llamados protocolos informales y protocolos aplicados por el compilador llamados protocolos formales .

Un protocolo informal es una lista de métodos que una clase puede optar por implementar. Está especificado en la documentación, ya que no tiene presencia en el idioma. Los protocolos informales se implementan como una categoría (ver más abajo) en NSObject y, a menudo, incluyen métodos opcionales que, si se implementan, pueden cambiar el comportamiento de una clase. Por ejemplo, una clase de campo de texto podría tener un delegado que implemente un protocolo informal con un método opcional para completar automáticamente el texto escrito por el usuario. El campo de texto descubre si el delegado implementa ese método (mediante reflexión ) y, de ser así, llama al método del delegado para admitir la función de autocompletar.

Un protocolo formal es similar a una interfaz en Java, C# y Ada 2005 . Es una lista de métodos que cualquier clase puede declararse implementar. Las versiones de Objective-C anteriores a la 2.0 requerían que una clase implementara todos los métodos en un protocolo que declaraba adoptar; el compilador emitirá un error si la clase no implementa todos los métodos de sus protocolos declarados. Objective-C 2.0 agregó soporte para marcar ciertos métodos en un protocolo como opcional, y el compilador no impondrá la implementación de métodos opcionales.

Se debe declarar una clase para implementar ese protocolo para que se diga que se ajusta a él. Esto es detectable en tiempo de ejecución. Los protocolos formales no pueden proporcionar ninguna implementación; simplemente aseguran a quienes llaman que las clases que se ajustan al protocolo proporcionarán implementaciones. En la biblioteca NeXT/Apple, el sistema de objetos distribuidos utiliza con frecuencia protocolos para representar las capacidades de un objeto que se ejecuta en un sistema remoto.

la sintaxis

@protocol  NSLocking -  ( void ) bloqueo ; -  ( anular ) desbloquear ; @fin

denota que existe la idea abstracta de bloquear. Al indicar en la definición de clase que el protocolo está implementado,

@interface  NSLock  : NSObject <NSLocking> // ... @end _ 

Las instancias de NSLock afirman que proporcionarán una implementación para los dos métodos de instancia.

Escritura dinámica

Objective-C, al igual que Smalltalk, puede utilizar escritura dinámica : a un objeto se le puede enviar un mensaje que no está especificado en su interfaz. Esto puede permitir una mayor flexibilidad, ya que permite que un objeto "capture" un mensaje y lo envíe a un objeto diferente que pueda responder al mensaje de manera adecuada, o también enviar el mensaje a otro objeto. Este comportamiento se conoce como reenvío o delegación de mensajes (ver más abajo). Alternativamente, se puede utilizar un controlador de errores en caso de que el mensaje no se pueda reenviar. Si un objeto no reenvía un mensaje, no responde o maneja un error, entonces el sistema generará una excepción de tiempo de ejecución. [24] Si los mensajes se envían a nil (el puntero de objeto nulo), se ignorarán silenciosamente o generarán una excepción genérica, dependiendo de las opciones del compilador.

Opcionalmente, también se puede agregar información de escritura estática a las variables. Luego, esta información se verifica en el momento de la compilación. En las siguientes cuatro afirmaciones se proporciona información de tipo cada vez más específica. Las declaraciones son equivalentes en tiempo de ejecución, pero la información adicional permite al compilador advertir al programador si el argumento pasado no coincide con el tipo especificado.

-  ( void ) setMyValue: ( id ) foo ;

En la declaración anterior, foo puede ser de cualquier clase.

-  ( void ) setMyValue : ( id <NSCopying> ) foo ; _

En la declaración anterior, foo puede ser una instancia de cualquier clase que cumpla con el NSCopyingprotocolo.

-  ( void ) setMyValue: ( NSNumber * ) foo ; 

En la declaración anterior, foo debe ser una instancia de la clase NSNumber .

-  ( void ) setMyValue : ( NSNumber <NSCopying> * ) foo ; _ 

En la declaración anterior, foo debe ser una instancia de la clase NSNumber y debe ajustarse al NSCopyingprotocolo.

En Objective-C, todos los objetos se representan como punteros y no se permite la inicialización estática. El objeto más simple es el tipo al que apunta id ( objc_obj * ), que solo tiene un puntero isa que describe su clase. Otros tipos de C, como valores y estructuras, no cambian porque no forman parte del sistema de objetos. Esta solución difiere del modelo de objetos de C++, donde se unen estructuras y clases.

Reenvío

Objective-C permite el envío de un mensaje a un objeto que puede no responder. En lugar de responder o simplemente descartar el mensaje, un objeto puede reenviar el mensaje a un objeto que pueda responder. El reenvío se puede utilizar para simplificar la implementación de ciertos patrones de diseño , como el patrón de observador o el patrón de proxy .

El tiempo de ejecución de Objective-C especifica un par de métodos en Object

Un objeto que desee implementar el reenvío sólo necesita anular el método de reenvío con un nuevo método para definir el comportamiento de reenvío. No es necesario anular el método de acción performv:: , ya que este método simplemente realiza una acción basada en el selector y los argumentos. Observe el tipo, que es el tipo de mensajes en Objective-C.SEL

Nota: en OpenStep, Cocoa y GNUstep, los marcos comúnmente utilizados de Objective-C, no se usa la clase Object . El método de la clase NSObject se utiliza para realizar el reenvío.- (void)forwardInvocation:(NSInvocation *)anInvocation

Ejemplo

A continuación se muestra un ejemplo de un programa que demuestra los conceptos básicos del reenvío.

Reenviador.h
#importar <objc/Object.h>@interface  Reenviador  : Objeto  { id destinatario ; // El objeto al que queremos reenviar el mensaje. }   // Métodos de acceso. -  ( identificación ) destinatario ; -  ( identificación ) setRecipient: ( identificación ) _destinatario ; @fin
Reenviador.m
#importar "Reenviador.h"@implementation  Forwarder -  ( retval_t ) forward: ( SEL ) sel args: ( arglist_t ) args { /*  * Verifique si el destinatario realmente responde al mensaje.  * Esto puede ser deseable o no, por ejemplo, si un destinatario  * a su vez no responde al mensaje, podría reenviarlo  * él mismo.  */ if ([ el destinatario responde al selector : sel ]) { retorno [ destinatario performv : sel args : args ]; } else { return [ auto error : "El destinatario no responde" ]; } }                  -  ( id ) setRecipient: ( id ) _recipient { [ liberación automática del destinatario ]; destinatario = [ _recipient retener ]; regresar a uno mismo ; }         -  ( id ) destinatario { destinatario de devolución ; } @fin   
Destinatario.h
#importar <objc/Object.h>// Un objeto Destinatario simple. @interface  Destinatario  : Objeto -  ( id ) hola ; @fin
Destinatario.m
#importar "Destinatario.h"@implementation  Destinatario-  ( id ) hola { printf ( "¡El destinatario dice hola! \n " );   regresar a uno mismo ; } @fin
principal.m
#import "Reenviador.h" #import "Destinatario.h"int main ( void ) { Reenviador * reenviador = [ Reenviador nuevo ]; Destinatario * destinatario = [ Destinatario nuevo ];             [ reenviador setRecipient : destinatario ]; // Establece el destinatario. /*  * ¡Observe que el reenviador no responde a un mensaje de saludo! Será  * reenviado. Todos los métodos no reconocidos se reenviarán al  * destinatario  * (si el destinatario responde a ellos, como está escrito en el reenviador)  */ [ reenviador hola ];      [ liberación del destinatario ]; [ liberación del reenviador ];    devolver 0 ; } 

Notas

Cuando se compila usando gcc , el compilador informa:

$ gcc  -x  objetivo-c  -Wno-import  Forwarder.m  Recipient.m  main.m  -lobjc main.m: En función `main': main.m:12: advertencia: `Forwarder' no responde a `hello' ps

El compilador informa lo señalado anteriormente, que el reenviador no responde a los mensajes de saludo. En esta circunstancia, es seguro ignorar la advertencia ya que se implementó el reenvío. Al ejecutar el programa se produce este resultado:

$ ./a.out ¡El destinatario saluda!

Categorías

Durante el diseño de Objective-C, una de las principales preocupaciones fue la mantenibilidad de grandes bases de código. La experiencia en el mundo de la programación estructurada había demostrado que una de las principales formas de mejorar el código era dividirlo en partes más pequeñas. Objective-C tomó prestado y amplió el concepto de categorías de las implementaciones de Smalltalk para ayudar con este proceso. [25]

Además, los métodos dentro de una categoría se agregan a una clase en tiempo de ejecución . Por lo tanto, las categorías permiten al programador agregar métodos a una clase existente (una clase abierta ) sin la necesidad de recompilar esa clase o incluso tener acceso a su código fuente. Por ejemplo, si un sistema no contiene un corrector ortográfico en su implementación de String, se podría agregar sin modificar el código fuente de String.

Los métodos dentro de las categorías se vuelven indistinguibles de los métodos de una clase cuando se ejecuta el programa. Una categoría tiene acceso completo a todas las variables de instancia dentro de la clase, incluidas las variables privadas.

Si una categoría declara un método con la misma firma de método que un método existente en una clase, se adopta el método de la categoría. Por lo tanto, las categorías no sólo pueden agregar métodos a una clase, sino también reemplazar métodos existentes. Esta característica se puede utilizar para corregir errores en otras clases reescribiendo sus métodos o para provocar un cambio global en el comportamiento de una clase dentro de un programa. Si dos categorías tienen métodos con el mismo nombre pero con firmas de método diferentes, no está definido qué método de categoría se adopta.

Otros idiomas han intentado agregar esta característica de diversas maneras. TOM llevó el sistema Objective-C un paso más allá y también permitió la adición de variables. Otros lenguajes han utilizado soluciones basadas en prototipos , siendo el más notable Self .

Los lenguajes C# y Visual Basic.NET implementan una funcionalidad superficialmente similar en forma de métodos de extensión , pero estos carecen de acceso a las variables privadas de la clase. [26] Ruby y varios otros lenguajes de programación dinámica se refieren a la técnica como " parche de mono ".

Logtalk implementa un concepto de categorías (como entidades de primera clase) que incluye la funcionalidad de categorías de Objective-C (las categorías de Logtalk también se pueden usar como unidades de composición detalladas al definir, por ejemplo, nuevas clases o prototipos; en particular, una categoría de Logtalk puede ser prácticamente importado por cualquier número de clases y prototipos).

Ejemplo de uso de categorías

Este ejemplo construye una clase Integer , definiendo primero una clase básica con solo métodos de acceso implementados y agregando dos categorías, Arithmetic y Display , que extienden la clase básica. Si bien las categorías pueden acceder a los miembros de datos privados de la clase base, a menudo es una buena práctica acceder a estos miembros de datos privados a través de los métodos de acceso, lo que ayuda a mantener las categorías más independientes de la clase base. La implementación de dichos descriptores de acceso es un uso típico de las categorías. Otra es usar categorías para agregar métodos a la clase base. Sin embargo, no se considera una buena práctica utilizar categorías para anular subclases, también conocido como parche de mono . Los protocolos informales se implementan como una categoría en la clase base NSObject . Por convención, los archivos que contienen categorías que amplían las clases base tomarán el nombre BaseClass+ExtensionClass.h .

Entero.h
#importar <objc/Object.h>@interface  Entero  : Objeto  { int entero ; }  -  ( int ) entero ; -  ( identificación ) entero: ( int ) _entero ; @fin
Entero.m
#importar "Entero.h"@implementation  Entero -  ( int )  entero { return entero ; }   -  ( id )  entero: ( int ) _entero { entero = _entero ; regresar a uno mismo ; } @fin        
Entero+Aritmética.h
#importar "Entero.h"@interface  Entero  (Aritmética) -  ( id )  agregar: ( Entero * ) sumando ; - ( id ) sub: ( Entero * ) sustraendo ; @fin        
Entero+Aritmética.m
#importar "Entero+Aritmética.h"@implementation  Entero  (Aritmética) -  ( id )  agregar: ( Entero * ) sumando { return [ auto entero : [ auto entero ] + [ sumando entero ]]; }            -  ( id )  sub: ( Entero * ) sustraendo { return [ auto entero : [ auto entero ] - [ sustraendo entero ] ]; } @fin            
Entero+Pantalla.h
#importar "Entero.h"@interface  Entero  (Pantalla) -  ( id )  showstars ; -  ( identificación )  muestra ; @fin
Entero+Pantalla.m
# importar "Entero+Pantalla.h"@implementation  Entero  (Pantalla) -  ( id )  showstars { int i , x = [ self integer ]; para ( i = 0 ; i < x ; i ++ ) { printf ( "*" ); } printf ( " \n " );                    regresar a uno mismo ; } -  ( id )  showint { printf ( "%d \n " , [ entero propio ]);     regresar a uno mismo ; } @fin 
principal.m
#importar "Entero.h"#importar "Entero+Aritmética.h"#importar "Entero+Pantalla.h"int principal ( vacío ) {   Entero * num1 = [ Entero nuevo ], * num2 = [ Entero nuevo ];         intx ; _  printf ( "Ingrese un número entero: " ); scanf ( "%d" , & x );  [ núm1 entero : x ];  [ num1 estrellas del espectáculo ];  printf ( "Ingrese un número entero: " ); scanf ( "%d" , & x );  [ núm2 entero : x ];  [ num2 estrellas del espectáculo ];  [ num1 agregar : num2 ];  [ num1 muestra ];  devolver 0 ; }

Notas

La compilación se realiza, por ejemplo, mediante:

$ gcc  -x  objetivo-c  principal.m  Entero.m  Entero+Aritmética.m  Entero+Pantalla.m  -lobjc

Se puede experimentar omitiendo #import "Integer+Arithmetic.h"(línea 2) y (línea 21) y omitiendo Integer+Arithmetic.m en la compilación. El programa seguirá ejecutándose. Esto significa que es posible mezclar y combinar categorías adicionales si es necesario; Si una categoría no necesita tener alguna capacidad, simplemente no se puede compilar.[num1 add:num2]

posando

Objective-C permite que una clase reemplace completamente a otra clase dentro de un programa. Se dice que la clase reemplazante "se hace pasar por" la clase objetivo.

La presentación de clases se declaró obsoleta con Mac OS X v10.5 y no está disponible en el tiempo de ejecución de 64 bits. Se puede lograr una funcionalidad similar utilizando el método swizzling en categorías, que intercambia la implementación de un método con la de otro que tiene la misma firma.

Para las versiones que aún admiten la pose, todos los mensajes enviados a la clase de destino son recibidos por la clase de pose. Hay varias restricciones:

Posar, al igual que con las categorías, permite el aumento global de las clases existentes. Posar permite dos características ausentes en las categorías:

Por ejemplo,

@interface  Aplicación NSA personalizada  : Aplicación NSA @end@implementation  CustomNSApplication -  ( void )  setMainMenu: ( NSMenu * ) menu { // hacer algo con el menú } @end    class_poseAs ([ clase de aplicación NSA personalizada ], [ clase de aplicación NSA ]);    

Esto intercepta cada invocación de setMainMenu a NSApplication.

#importar

En el lenguaje C, la #includedirectiva de precompilación siempre hace que el contenido de un archivo se inserte en el código fuente en ese punto. Objective-C tiene la #importdirectiva equivalente, excepto que cada archivo se incluye solo una vez por unidad de compilación, lo que evita la necesidad de incluir guardias .

compilación gcc de linux

// ARCHIVO: hello.m #import <Foundation/Foundation.h> int main ( int argc , const char * argv []) { /* mi primer programa en Objective-C */ NSLog ( @"¡Hola mundo! \ norte " ); devolver 0 ; }           
$ # Compilar línea de comando para el compilador gcc y MinGW: $ gcc \  $ ( gnustep-config --objc-flags ) \ -o hello \ hello.m \ -L /GNUstep/System/Library/Libraries \ -lobjc \ -lgnustep -base              $ ./hola

Otras características

Las características de Objective-C a menudo permiten soluciones flexibles y, a menudo, sencillas a los problemas de programación.

Variantes de idioma

Objetivo-C++

Objective-C++ es una variante de lenguaje aceptada por el front-end de GNU Compiler Collection y Clang , que puede compilar archivos fuente que usan una combinación de sintaxis de C++ y Objective-C. Objective-C++ agrega a C++ las extensiones que Objective-C agrega a C. Como no se hace nada para unificar la semántica detrás de las distintas características del lenguaje, se aplican ciertas restricciones:

Objetivo-C 2.0

En la Conferencia Mundial de Desarrolladores de 2006 , Apple anunció el lanzamiento de "Objective-C 2.0", una revisión del lenguaje Objective-C para incluir "recolección de basura moderna, mejoras de sintaxis, [29] mejoras en el rendimiento del tiempo de ejecución, [30] y 64- soporte de bits". Mac OS X v10.5 , lanzado en octubre de 2007, incluía un compilador Objective-C 2.0. GCC 4.6 admite muchas características nuevas de Objective-C, como propiedades declaradas y sintetizadas, sintaxis de puntos, enumeración rápida, métodos de protocolo opcionales, atributos de método/protocolo/clase, extensiones de clase y una nueva API de tiempo de ejecución de GNU Objective-C. [31]

El nombre Objective-C 2.0 representa una ruptura en el sistema de versiones del lenguaje, ya que la última versión de Objective-C para NeXT fue "objc4". [32] Este nombre de proyecto se mantuvo en la última versión del código fuente de tiempo de ejecución Objective-C heredado en Mac OS X Leopard (10.5). [33]

Recolección de basura

Objective-C 2.0 proporcionó un recolector de basura generacional conservador opcional . Cuando se ejecuta en modo compatible con versiones anteriores , el tiempo de ejecución convierte las operaciones de recuento de referencias , como "retener" y "liberar", en no operativas . Todos los objetos estaban sujetos a recolección de basura cuando se habilitaba la recolección de basura. Los punteros C normales podrían calificarse con "__strong" para activar también las intercepciones del compilador de la barrera de escritura subyacente y así participar en la recolección de basura. [34] También se proporcionó un subsistema débil de puesta a cero de manera que los punteros marcados como "__weak" se establezcan en cero cuando se recopile el objeto (o más simplemente, la memoria del GC). El recolector de basura no existe en la implementación iOS de Objective-C 2.0. [35] La recolección de basura en Objective-C se ejecuta en un subproceso en segundo plano de baja prioridad y puede detenerse en eventos del usuario, con la intención de mantener la experiencia del usuario receptiva. [36]

La recolección de basura quedó obsoleta en Mac OS X v10.8 a favor del conteo automático de referencias (ARC). [37] Objective-C en iOS 7 que se ejecuta en ARM64 utiliza 19 bits de una palabra de 64 bits para almacenar el recuento de referencias, como una forma de punteros etiquetados . [38] [39]

Propiedades

Objective-C 2.0 introduce una nueva sintaxis para declarar variables de instancia como propiedades , con atributos opcionales para configurar la generación de métodos de acceso. Las propiedades son, en cierto sentido, variables de instancia pública; es decir, declarar una variable de instancia como una propiedad proporciona a las clases externas acceso (posiblemente limitado, por ejemplo, de sólo lectura) a esa propiedad. Una propiedad se puede declarar como "solo lectura" y se le puede proporcionar una semántica de almacenamiento como assign, copyo retain. De forma predeterminada, se consideran las propiedades atomic, lo que da como resultado un bloqueo que impide que varios subprocesos accedan a ellas al mismo tiempo. Se puede declarar una propiedad como nonatomic, lo que elimina este bloqueo.

@interface  Persona  : NSObject  { @public NSString * nombre ; @private int edad ; }    @property ( copia ) NSString * nombre ; @property ( solo lectura ) int edad ;    -  ( id ) initWithAge: ( int ) edad ; @fin

Las propiedades se implementan mediante la @synthesizepalabra clave, que genera métodos getter (y setter, si no son de solo lectura) de acuerdo con la declaración de propiedad. Alternativamente, los métodos getter y setter deben implementarse explícitamente, o @dynamicse puede usar la palabra clave para indicar que los métodos de acceso se proporcionarán por otros medios. Cuando se compila usando clang 3.1 o superior, todas las propiedades que no estén declaradas explícitamente con @dynamic, marcadas readonlyo que tengan getter y setter completos implementados por el usuario serán automáticamente implícitas @synthesize.

@implementation  Persona @synthesize nombre ; -  ( id ) initWithAge: ( int ) initAge { self = [ super init ]; if ( self ) { // NOTA: asignación directa de variable de instancia, no establecimiento de propiedad age = initAge ; } devolverse a sí mismo ; }               -  ( int ) edad { edad de retorno ; } @fin   

Se puede acceder a las propiedades utilizando la sintaxis tradicional de paso de mensajes, notación de puntos o, en la codificación de valores clave, por nombre a través de los métodos "valueForKey:"/"setValue:forKey:".

Persona * aPerson = [[ Persona alloc ] initWithAge : 53 ]; una persona . nombre = @"Steve" ; // NOTA: notación de puntos, utiliza un definidor sintetizado, // equivalente a [aPerson setName: @"Steve"]; NSLog ( @"Acceso por mensaje (%@), notación de puntos(%@), nombre de propiedad(% @) y " " acceso directo a variable de instancia(% @) " , [ nombre de unaPersona ], nombre de unaPersona , [ valor de unaPersonForKey : @"nombre" ], unaPersona -> nombre );                  

Para utilizar la notación de puntos para invocar descriptores de acceso a propiedades dentro de un método de instancia, se debe utilizar la palabra clave "self":

-  ( void ) presentarMyselfWithProperties: ( BOOL ) useGetter { NSLog ( @"Hola, mi nombre es %@." , ( useGetter ? self . nombre : nombre )); // NOTA: acceso getter vs. ivar }        

Las propiedades de una clase o protocolo pueden ser introspeccionadas dinámicamente .

int yo ; int propiedadCount = 0 ; objc_property_t * propertyList = class_copyPropertyList ([ clase aPerson ], & propertyCount );         for ( i = 0 ; i < propertyCount ; i ++ ) { objc_property_t * thisProperty = propertyList + i ; const char * nombrePropiedad = nombre_obtenerpropiedad ( * estaPropiedad ); NSLog ( @"La persona tiene una propiedad: '%s'" , nombre de propiedad ); }                     

Variables de instancia no frágiles

Objective-C 2.0 proporciona variables de instancia no frágiles cuando el tiempo de ejecución las admite (es decir, cuando se crea código para macOS de 64 bits y todo iOS). En el tiempo de ejecución moderno, se agrega una capa adicional de indirección al acceso a variables de instancia, lo que permite que el vinculador dinámico ajuste el diseño de la instancia en tiempo de ejecución. Esta característica permite dos mejoras importantes al código Objective-C:

Enumeración rápida

En lugar de utilizar un objeto NSEnumerator o índices para iterar a través de una colección, Objective-C 2.0 ofrece una sintaxis de enumeración rápida. En Objective-C 2.0, los siguientes bucles son funcionalmente equivalentes, pero tienen características de rendimiento diferentes.

// Usando NSEnumerator NSEnumerator * enumerador = [ thePeople objectEnumerator ]; Persona * p ;     while (( p = [ enumerador nextObject ]) != nil ) { NSLog ( @"%@ tiene %i años." , [ p nombre ], [ página edad ]); }            
// Usando índices para ( int i = 0 ; i < [ thePeople count ]; i ++ ) { Person * p = [ thePeople objectAtIndex : i ]; NSLog ( @"%@ tiene %i años." , [ p nombre ], [ página edad ]); }                    
// Usando enumeración rápida para ( Persona * p en thePeople ) { NSLog ( @"%@ tiene %i años." , [ p nombre ], [ página edad ]); }          

La enumeración rápida genera código más eficiente que la enumeración estándar porque las llamadas a métodos para enumerar objetos se reemplazan por aritmética de punteros utilizando el protocolo NSFastEnumeration. [40]

Extensiones de clase

Una extensión de clase tiene la misma sintaxis que una declaración de categoría sin nombre de categoría, y los métodos y propiedades declarados en ella se agregan directamente a la clase principal. Se utiliza principalmente como una alternativa a una categoría para agregar métodos a una clase sin anunciarlos en los encabezados públicos, con la ventaja de que para las extensiones de clase el compilador verifica que todos los métodos declarados de forma privada estén realmente implementados. [41]

Implicaciones para el desarrollo del cacao

Todas las aplicaciones Objective-C desarrolladas para macOS que utilizan las mejoras anteriores para Objective-C 2.0 son incompatibles con todos los sistemas operativos anteriores al 10.5 (Leopard). Dado que la enumeración rápida no genera exactamente los mismos archivos binarios que la enumeración estándar, su uso provocará que una aplicación falle en Mac OS X versión 10.4 o anterior.

Bloques

Blocks es una extensión no estándar para Objective-C (y C y C++ ) que utiliza una sintaxis especial para crear cierres . Los bloques solo son compatibles con Mac OS X 10.6 "Snow Leopard" o posterior, iOS 4 o posterior y GNUstep con libobjc2 1.7 y compilando con clang 3.1 o posterior. [42]

#include <stdio.h> #include <Block.h> typedef int ( ^ IntBlock )();    IntBlock MakeCounter ( int inicio , int incremento ) { __block int i = inicio ;           return Block_copy ( ^ { int ret = i ; i += incremento ; return ret ; });             }int main ( void ) { IntBlock micontador = MakeCounter ( 5 , 2 ); printf ( "Primera llamada: %d \n " , micontador ()); printf ( "Segunda llamada: %d \n " , micontador ()); printf ( "Tercera llamada: %d \n " , micontador ());              /* debido a que fue copiado, también debe liberarse */ Block_release ( mycounter );  devolver 0 ; } /* Salida:  Primera llamada: 5  Segunda llamada: 7  Tercera llamada: 9 */ 

Objetivo-C moderno

Apple ha agregado algunas funciones adicionales a Objective 2.0 con el tiempo. Las adiciones sólo se aplican al "compilador Apple LLVM ", es decir, la interfaz clang del lenguaje. De manera confusa, el control de versiones utilizado por Apple difiere del del LLVM ascendente; consulte Xcode § Versiones de la cadena de herramientas para obtener una traducción a los números de versión de LLVM de código abierto. [43]

Conteo automático de referencias

El conteo automático de referencias (ARC) es una característica en tiempo de compilación que elimina la necesidad de que los programadores administren manualmente los conteos de retención usando retainy release. [44] A diferencia de la recolección de basura , que ocurre en tiempo de ejecución, ARC elimina la sobrecarga de un proceso separado que administra los recuentos de retención. ARC y la gestión manual de la memoria no son mutuamente excluyentes; Los programadores pueden continuar usando código que no sea ARC en proyectos habilitados para ARC deshabilitando ARC para archivos de código individuales. Xcode también puede intentar actualizar automáticamente un proyecto a ARC.

ARC se introdujo en LLVM 3.0. Esto se traduce en Xcode 4.2 (2011) o el compilador Apple LLVM 3.0. [45]

Literales

Los tiempos de ejecución de NeXT y Apple Obj-C han incluido durante mucho tiempo una forma abreviada de crear nuevas cadenas, usando la sintaxis literal @"a new string", o pasando a constantes de CoreFoundation kCFBooleanTruey kCFBooleanFalsecon NSNumbervalores booleanos. El uso de este formato evita que el programador tenga que utilizar initWithStringmétodos más largos o similares al realizar determinadas operaciones.

Cuando se utiliza el compilador Apple LLVM 4.0 (Xcode 4.4) o posterior, también se pueden crear matrices, diccionarios y números ( NSArray, NSDictionaryclases ) utilizando sintaxis literal en lugar de métodos. [46] (El compilador 4.0 de Apple LLVM se traduce a LLVM de código abierto y Clang 3.1.) [47]NSNumber

Ejemplo sin literales:

NSArray * myArray = [ NSArray arrayWithObjects : objeto1 , objeto2 , objeto3 , nulo ]; NSDictionary * myDictionary1 = [ Diccionario NSDictionaryWithObject : algúnObjeto paraClave : @"clave" ]; NSDictionary * myDictionary2 = [ NSDictionary diccionarioWithObjectsAndKeys : objeto1 , clave1 , objeto2 , clave2 , nulo ]; NSNumber * myNumber = [ NSNumber numberWithInt : myInt ]; NSNumber * mySumNumber = [ NSNumber numberWithInt : ( 2 + 3 )]; NSNumber * myBoolNumber = [ NSNumber numberWithBool : ];                              

Ejemplo con literales:

NSArray * miArray = @[ objeto1 , objeto2 , objeto3 ] ; NSDictionary * myDictionary1 = @{ @"clave" : algúnObjeto } ; NSDictionary * myDictionary2 = @{ clave1 : objeto1 , clave2 : objeto2 } ; NSNumber * myNumber = @( myInt ) ; NSNumber * mySumNumber = @( 2 + 3 ) ; NSNumber * myBoolNumber = @YES ; NSNúmero * miNúmeroEntero = @8 ;                                  

Sin embargo, a diferencia de los literales de cadena , que se compilan en constantes en el ejecutable, estos literales se compilan en un código equivalente a las llamadas a métodos anteriores. En particular, bajo la gestión de memoria contada manualmente por referencia, estos objetos se liberan automáticamente, lo que requiere mayor cuidado cuando, por ejemplo, se utilizan con variables de función estática u otros tipos de variables globales.

Subscripción

Cuando se utiliza el compilador Apple LLVM 4.0 o posterior, las matrices y diccionarios ( NSArrayy NSDictionaryclases) se pueden manipular mediante subíndices. [46] Los subíndices se pueden utilizar para recuperar valores de índices (matriz) o claves (diccionario) y, con objetos mutables, también se pueden utilizar para establecer objetos en índices o claves. En el código, los subíndices se representan mediante corchetes [ ]. [48]

Ejemplo sin subíndice:

id objeto1 = [ someArray objectAtIndex : 0 ]; id objeto2 = [ algún objeto de diccionario para clave : @"clave" ]; [ someMutableArray reemplazaObjectAtIndex : 0 conObjeto : objeto3 ]; [ someMutableDictionary setObject : object4 forKey : @"key" ];            

Ejemplo con subíndice:

id objeto1 = algunamatriz [ 0 ]; id objeto2 = algúnDiccionario [ @"clave" ]; someMutableArray [ 0 ] = objeto3 ; algúnDiccionarioMutable [ @"clave" ] = objeto4 ;          

Sintaxis Objective-C "moderna" (1997)

Después de la compra de NeXT por parte de Apple, se intentó hacer que el lenguaje fuera más aceptable para los programadores más familiarizados con Java que Smalltalk. Uno de estos intentos fue introducir lo que se denominó "sintaxis moderna" para Objective-C en ese momento [49] (a diferencia de la sintaxis "clásica" actual). No hubo ningún cambio en el comportamiento, se trataba simplemente de una sintaxis alternativa. En lugar de escribir una invocación de método como

 objeto = [[ MiClase alloc ] init ]; [ objeto primeraEtiqueta : parámetro1 segundaEtiqueta : param2 ];         

En cambio, fue escrito como

 objeto = ( MiClase . alloc ). en eso ; objeto . etiquetas ( param1 , param2 );       

Asimismo, las declaraciones pasaron de la forma

 - ( void ) primeraEtiqueta : ( int ) param1 segundaEtiqueta : ( int ) param2 ;    

a

 - ( void ) etiquetas ( int param1 , int param2 );       

Esta sintaxis "moderna" ya no es compatible con los dialectos actuales del lenguaje Objective-C.

objeto-mulle

El proyecto mulle-objc es otra reimplementación de Objective-C. Admite compiladores GCC o Clang / LLVM como backends. Se diferencia de otros tiempos de ejecución en términos de sintaxis, semántica y compatibilidad ABI. Es compatible con Linux, FreeBSD y Windows.

Compilador de objetos portátil

Además de la implementación GCC / NeXT / Apple , que agregó varias extensiones a la implementación original de Stepstone , también existe otra implementación Objective-C gratuita y de código abierto llamada Portable Object Compiler. [50] El conjunto de extensiones implementadas por el Compilador de Objetos Portátil difiere de la implementación de GCC/NeXT/Apple; en particular, incluye bloques similares a Smalltalk para Objective-C, mientras que carece de protocolos y categorías, dos características utilizadas ampliamente en OpenStep y sus derivados y parientes. En general, POC representa una etapa anterior a NeXT en la evolución del lenguaje, más o menos conforme al libro de Brad Cox de 1991.

También incluye una biblioteca de tiempo de ejecución llamada ObjectPak, que se basa en la biblioteca ICPak101 original de Cox (que a su vez deriva de la biblioteca de clases Smalltalk-80) y es radicalmente diferente de OpenStep FoundationKit.

GEOS Objetivo-C

El sistema PC GEOS utilizaba un lenguaje de programación conocido como GEOS Objective-C o goc ; [51] a pesar de la similitud del nombre, los dos idiomas son similares sólo en el concepto general y el uso de palabras clave con el prefijo @.

Sonido metálico

El conjunto de compiladores Clang , parte del proyecto LLVM , implementa Objective-C y otros lenguajes. Después de que GCC 4.3 (2008) cambiara a GPLv3, Apple lo abandonó en favor de clang, un compilador que tiene más poder legal para modificar. Como resultado, muchas de las características modernas del lenguaje Objective-C solo son compatibles con Clang.

El esquema de control de versiones de Apple para su "compilador LLVM" basado en clang difiere del control de versiones de código abierto de LLVM. Consulte Xcode § Versiones de la cadena de herramientas para obtener una traducción [43]

GNU, GNUstep y WinObjC

El proyecto GNU ha estado interesado durante mucho tiempo en una plataforma para portar los programas NeXT y Obj-C. El ChangeLog para el directorio libobjc en GCC sugiere que existía antes de 1998 (GCC 2.95), y su README apunta además a una reescritura en 1993 (GCC 2.4). [52]

El código fuente de la interfaz NeXT se publicó ya que se creó como parte de GCC, y se publicó la licencia pública GNU que obliga a quienes realizan trabajos derivados a hacerlo. [ ¿ cuando? ] Apple continuó esta tradición al lanzar su bifurcación de GCC hasta 4.2.1, después de lo cual abandonaron el compilador. Los mantenedores de GCC asumieron los cambios, pero no invirtieron mucho en soportar características más nuevas como el lenguaje Objective-C 2.0. [32] : ¿Qué compilador 

Los desarrolladores de GNUstep, interesados ​​en el nuevo lenguaje, bifurcaron GCC libobjc a un proyecto independiente de GCC llamado libobjc2 en 2009. También organizaron que el tiempo de ejecución se usara con Clang para aprovechar la sintaxis del nuevo lenguaje. [32] : Qué compilador  GCC se movió lentamente al mismo tiempo, pero en GCC 4.6.0 (2011) también pasaron a Objective-C 2.0 en su libobjc. [31] [53] La documentación de GNUstep sugiere que la implementación de GCC aún carece de soporte para bloques, variables no frágiles y el ARC más nuevo. [32] : ¿Qué tiempo de ejecución 

Microsoft bifurcó libobjc2 en una parte de WinObjC , el puente de iOS para la plataforma universal de Windows , en 2015. Combinado con su propia implementación de Cocoa Touch y las API subyacentes, el proyecto permite la reutilización del código de la aplicación iOS dentro de las aplicaciones para UWP. [54]

En Windows, las herramientas de desarrollo Objective-C se pueden descargar en el sitio web de GNUStep. El sistema de desarrollo GNUStep consta de los siguientes paquetes: GNUstep MSYS System, GNUstep Core, GNUstep Devel, GNUstep Cairo, ProjectCenter IDE (como Xcode, pero no tan complejo), Gorm (Interface Builder como Xcode NIB builder). Estos instaladores binarios no se han actualizado desde 2016, [55] por lo que podría ser una mejor idea simplemente instalarlos compilando en Cygwin o MSYS2 .

Uso de la biblioteca

Hoy en día, Objective-C se utiliza a menudo junto con una biblioteca fija de objetos estándar (a menudo conocida como "kit" o "framework"), como Cocoa , GNUstep u ObjFW. Estas bibliotecas suelen venir con el sistema operativo: las bibliotecas GNUstep suelen venir con distribuciones basadas en Linux y Cocoa viene con macOS. El programador no está obligado a heredar la funcionalidad de la clase base existente (NSObject/OFObject). Objective-C permite la declaración de nuevas clases raíz que no heredan ninguna funcionalidad existente. Originalmente, los entornos de programación basados ​​en Objective-C normalmente ofrecían una clase Objeto como clase base de la cual heredaban casi todas las demás clases. Con la introducción de OpenStep, NeXT creó una nueva clase base llamada NSObject, que ofrecía características adicionales sobre Object (un énfasis en el uso de referencias de objetos y recuento de referencias en lugar de punteros sin formato, por ejemplo). Casi todas las clases de Cocoa heredan de NSObject.

El cambio de nombre no solo sirvió para diferenciar el nuevo comportamiento predeterminado de las clases dentro de la API de OpenStep, sino que también permitió que el código que usaba Object, la clase base original utilizada en NeXTSTEP (y, más o menos, otras bibliotecas de clases de Objective-C), coexistir en el mismo tiempo de ejecución con el código que usó NSObject (con algunas limitaciones). La introducción del prefijo de dos letras también se convirtió en una forma simplista de espacios de nombres, de la que carece Objective-C. El uso de un prefijo para crear un identificador de paquete informal se convirtió en un estándar de codificación informal en la comunidad Objective-C y continúa hasta el día de hoy.

Más recientemente, han comenzado a aparecer administradores de paquetes, como CocoaPods , que pretende ser a la vez un administrador de paquetes y un repositorio de paquetes. Gran parte del código Objective-C de código abierto escrito en los últimos años ahora se puede instalar utilizando CocoaPods.

Análisis de la lengua.

Las implementaciones de Objective-C utilizan un sistema de ejecución ligero escrito en C [ cita necesaria ] , lo que añade poco al tamaño de la aplicación. Por el contrario, la mayoría de los sistemas orientados a objetos en el momento de su creación utilizaban grandes tiempos de ejecución de máquinas virtuales . Los programas escritos en Objective-C tienden a no ser mucho más grandes que el tamaño de su código y el de las bibliotecas (que generalmente no necesitan ser incluidas en la distribución del software), a diferencia de los sistemas Smalltalk donde se necesitaba una gran cantidad de memoria. Se utiliza sólo para abrir una ventana. Las aplicaciones Objective-C tienden a ser más grandes que las aplicaciones C o C++ similares porque la escritura dinámica Objective-C no permite eliminar o insertar métodos. Dado que el programador tiene tanta libertad para delegar, reenviar llamadas, crear selectores sobre la marcha y pasarlos al sistema de ejecución, el compilador de Objective-C no puede asumir que es seguro eliminar métodos no utilizados o realizar llamadas en línea.

Del mismo modo, el lenguaje se puede implementar sobre compiladores de C existentes (en GCC , primero como preprocesador y luego como módulo) en lugar de como un nuevo compilador. Esto permite a Objective-C aprovechar la enorme colección existente de código C, bibliotecas, herramientas, etc. Las bibliotecas de C existentes se pueden empaquetar en contenedores de Objective-C para proporcionar una interfaz de estilo OO. En este aspecto, es similar a la biblioteca GObject y al lenguaje Vala , que se utilizan ampliamente en el desarrollo de aplicaciones GTK .

Todos estos cambios prácticos redujeron la barrera de entrada , probablemente el mayor problema para la aceptación generalizada de Smalltalk en la década de 1980.

Una crítica común es que Objective-C no tiene soporte de lenguaje para espacios de nombres . En cambio, los programadores se ven obligados a agregar prefijos a los nombres de sus clases, que tradicionalmente son más cortos que los nombres de los espacios de nombres y, por lo tanto, más propensos a colisiones. A partir de 2007, todas las clases y funciones de macOS en el entorno de programación Cocoa tienen el prefijo "NS" (por ejemplo, NSObject, NSButton) para identificarlas como pertenecientes al núcleo de macOS o iOS; el "NS" deriva de los nombres de las clases tal como se definieron durante el desarrollo de NeXTSTEP .

Dado que Objective-C es un superconjunto estricto de C, no trata los tipos primitivos de C como objetos de primera clase .

A diferencia de C++ , Objective-C no admite la sobrecarga de operadores . Además, a diferencia de C++, Objective-C permite que un objeto herede directamente solo de una clase (prohibiendo la herencia múltiple ). Sin embargo, en la mayoría de los casos, se pueden utilizar categorías y protocolos como formas alternativas de lograr los mismos resultados.

Debido a que Objective-C utiliza tipificación dinámica en tiempo de ejecución y debido a que todas las llamadas a métodos son llamadas a funciones (o, en algunos casos, llamadas al sistema), muchas optimizaciones de rendimiento comunes no se pueden aplicar a los métodos de Objective-C (por ejemplo: inserción, propagación constante, optimizaciones interprocedurales, y reemplazo escalar de agregados). Esto limita el rendimiento de las abstracciones de Objective-C en relación con abstracciones similares en lenguajes como C++ donde tales optimizaciones son posibles.

Gestión de la memoria

Las primeras versiones de Objective-C no admitían la recolección de basura . En ese momento, esta decisión fue un tema de debate, y muchas personas consideraron que los largos "tiempos muertos" (cuando Smalltalk realizaba la recopilación) dejarían todo el sistema inutilizable. Algunas implementaciones de terceros han agregado esta característica (en particular, GNUstep usando Boehm ), y Apple la ha implementado a partir de Mac OS X v10.5 . [56] Sin embargo, en versiones más recientes de macOS e iOS, la recolección de basura ha quedado obsoleta en favor del conteo automático de referencias (ARC), introducido en 2011.

Con ARC, el compilador inserta llamadas de retención y liberación automáticamente en el código Objective-C basándose en el análisis de código estático . La automatización libera al programador de tener que escribir un código de gestión de memoria. ARC también agrega referencias débiles al lenguaje Objective-C. [57]

Diferencias filosóficas entre Objective-C y C++

El diseño y la implementación de C++ y Objective-C representan enfoques fundamentalmente diferentes para extender C.

Además del estilo de programación procedimental de C, C++ admite directamente ciertas formas de programación orientada a objetos , programación genérica y metaprogramación . C++ también viene con una gran biblioteca estándar que incluye varias clases de contenedores . De manera similar, Objective-C agrega programación orientada a objetos , escritura dinámica y reflexión a C. Objective-C no proporciona una biblioteca estándar per se , pero en la mayoría de los lugares donde se usa Objective-C, se usa con una biblioteca similar a OpenStep. biblioteca como OPENSTEP , Cocoa o GNUstep , que proporciona una funcionalidad similar a la biblioteca estándar de C++.

Una diferencia notable es que Objective-C proporciona soporte de tiempo de ejecución para características reflectantes , mientras que C++ agrega sólo una pequeña cantidad de soporte de tiempo de ejecución a C. En Objective-C, se puede consultar a un objeto sobre sus propias propiedades, por ejemplo, si responderá a un determinado mensaje. En C++, esto no es posible sin el uso de bibliotecas externas.

El uso de la reflexión es parte de la distinción más amplia entre características dinámicas (en tiempo de ejecución) y características estáticas (en tiempo de compilación) de un lenguaje. Aunque Objective-C y C++ emplean cada uno una combinación de ambas características, Objective-C está decididamente orientado a decisiones en tiempo de ejecución, mientras que C++ está orientado a decisiones en tiempo de compilación. La tensión entre programación dinámica y estática involucra muchas de las compensaciones clásicas en programación: las características dinámicas agregan flexibilidad, las características estáticas agregan velocidad y verificación de tipos.

La programación genérica y la metaprogramación se pueden implementar en ambos lenguajes utilizando polimorfismo en tiempo de ejecución . En C++ esto toma la forma de funciones virtuales e identificación de tipo de tiempo de ejecución , mientras que Objective-C ofrece escritura y reflexión dinámicas. Tanto Objective-C como C++ admiten polimorfismo en tiempo de compilación ( funciones genéricas ), y Objective-C solo agregó esta característica en 2015.

Ver también

Referencias

  1. ^ "Plataformas y versiones de tiempo de ejecución". Desarrollador.apple.com . Archivado desde el original el 20 de julio de 2016 . Consultado el 24 de diciembre de 2017 .
  2. ^ Lattner, Chris (3 de junio de 2014). "Página de inicio de Chris Lattner". Chris Lattner. Archivado desde el original el 4 de junio de 2014 . Consultado el 3 de junio de 2014 . El lenguaje Swift es el producto del esfuerzo incansable de un equipo de expertos en lenguaje, gurús de la documentación, ninjas de optimización de compiladores y un grupo interno increíblemente importante de pruebas internas que brindaron comentarios para ayudar a refinar y probar ideas. Por supuesto, también se benefició enormemente de las experiencias ganadas con esfuerzo por muchos otros lenguajes en el campo, extrayendo ideas de Objective-C, Rust, Haskell, Ruby, Python, C#, CLU y muchos otros para enumerarlos.
  3. ^ ab "Marcos de aplicaciones". Manzana. Junio ​​de 2014. Archivado desde el original el 16 de febrero de 2019 . Consultado el 13 de febrero de 2019 .
  4. ^ Singh, Amit (diciembre de 2003). "Una breve historia de Mac OS X". Componentes internos de Mac OS X. Archivado desde el original el 14 de mayo de 2012 . Consultado el 11 de junio de 2012 .
  5. ^ Garling, Caleb. "El lenguaje de codificación del iPhone ahora es el tercero más popular del mundo". Cableado . Archivado desde el original el 9 de septiembre de 2013 . Consultado el 20 de mayo de 2013 .
  6. ^ Wentk, Richard (2009). Cocoa: Volumen 5 de Developer Reference Apple Developer Series. John Wiley e hijos. ISBN 978-0-470-49589-6. Archivado desde el original el 16 de febrero de 2017 . Consultado el 22 de julio de 2016 .
  7. ^ Biancuzzi, Federico; Guardián, Shane (2009). Mentes maestras de la programación. O'Reilly Media, Inc. págs. 242–246. ISBN 978-0-596-51517-1. Archivado desde el original el 17 de febrero de 2017 . Consultado el 22 de julio de 2016 .
  8. ^ Cox, Brad (1983). "El precompilador orientado a objetos: programación de métodos Smalltalk 80 en lenguaje C". Avisos ACM SIGPLAN . Nueva York, Nueva York: ACM . 18 (1). doi :10.1145/948093.948095. S2CID  6975032 . Consultado el 17 de febrero de 2011 .
  9. ^ "Lisp y Readline comunes". GitHub . Archivado desde el original el 6 de septiembre de 2014 . Consultado el 15 de septiembre de 2014 . El problema surgió por primera vez cuando NeXT propuso distribuir un GCC modificado en dos partes y permitir que el usuario las vincule. Jobs me preguntó si esto era legal. Me pareció en su momento que sí, siguiendo un razonamiento como el que estás usando; pero como el resultado fue muy indeseable para el software libre, dije que tendría que preguntarle al abogado. Lo que dijo el abogado me sorprendió; Dijo que los jueces considerarían tales planes como "subterfugios" y serían muy duros con ellos. Dijo que un juez preguntaría si es "realmente" un programa, en lugar de cómo está etiquetado. Así que volví a hablar con Jobs y le dije que creíamos que la GPL no permitía su plan. El resultado directo de esto es que ahora tenemos una interfaz Objective C. Querían distribuir el analizador de Objective C como un paquete propietario separado para vincularlo con el back-end de GCC, pero como yo no estaba de acuerdo con que esto estuviera permitido, lo hicieron gratuito.
  10. ^ "GNUstep: Introducción". Desarrolladores GNUstep/Proyecto GNU. Archivado desde el original el 6 de agosto de 2012 . Consultado el 29 de julio de 2012 .
  11. ^ "Kresten Krab Thorup | LinkedIn". www.linkedin.com . Archivado desde el original el 15 de julio de 2014 . Consultado el 23 de junio de 2016 .
  12. ^ "Escribir código Objective-C". apple.com. 23 de abril de 2013. Archivado desde el original el 24 de diciembre de 2013 . Consultado el 22 de diciembre de 2013 .
  13. ^ "Campamento de entrenamiento de Objective-C". Archivado desde el original el 11 de febrero de 2018 . Consultado el 11 de febrero de 2018 . Objective-C es un superconjunto estricto de ANSI C
  14. ^ "Examen de Objective-C". Archivado desde el original el 4 de septiembre de 2014 . Consultado el 4 de septiembre de 2014 . Objective-C es un superconjunto estricto de C orientado a objetos
  15. ^ Lee, Keith (3 de septiembre de 2013). Pro Objective-C. Presione. ISBN 9781430250500. Archivado desde el original el 14 de mayo de 2018 . Consultado el 24 de diciembre de 2017 a través de Google Books.
  16. ^ "Etiquetas para encabezados Objective-C". Archivado desde el original el 1 de abril de 2017 . Consultado el 11 de febrero de 2018 . Objective-C es un superconjunto de C
  17. ^ "AppScan Source 8.7 ya está disponible". Archivado desde el original el 3 de febrero de 2017 . Consultado el 11 de febrero de 2018 . El lenguaje de programación Objective-C es un superconjunto del lenguaje de programación C.
  18. ^ Apple, Inc. (19 de octubre de 2009). "Resolución del método dinámico". Guía de programación en tiempo de ejecución de Objective-C . Archivado desde el original el 7 de septiembre de 2010 . Consultado el 25 de noviembre de 2014 .
  19. ^ Apple, Inc. (19 de octubre de 2009). "Evitar errores de mensajería". El lenguaje de programación Objective-C . Archivado desde el original el 8 de septiembre de 2010.
  20. ^ "objc_msgSend - Tiempo de ejecución de Objective-C". Documentación para desarrolladores de Apple . Consultado el 10 de febrero de 2020 .
  21. ^ "Mensajería con el tiempo de ejecución GNU Objective-C". Usando la colección de compiladores GNU (GCC) . Consultado el 10 de febrero de 2020 .
  22. ^ "Categoría". Desarrollador de Apple (Competencias básicas de Cocoa) .
  23. ^ Dalrymple, Marcos; Knaster, Scott (27 de junio de 2012). Aprenda Objective-C en Mac . Presione. pag. 9.ISBN _ 9781430241881. La extensión .m originalmente significaba "mensajes" cuando se introdujo por primera vez Objective-C, en referencia a una característica central de Objective-C.
  24. ^ "Guía de programación en tiempo de ejecución de Objective-C". Apple Inc. Archivado desde el original el 4 de abril de 2014 . Consultado el 21 de octubre de 2013 .
  25. ^ "ACM SIGGRAPH 1983 Número 8 - Smalltalk". Archivado desde el original el 15 de abril de 2009 . Consultado el 7 de octubre de 2008 .
  26. ^ "Métodos de extensión (Guía de programación de C#)". Microsoft. Octubre de 2010. Archivado desde el original el 11 de julio de 2011 . Consultado el 10 de julio de 2011 .
  27. ^ "Usando C++ con Objective-C". Biblioteca de referencia de Mac OS X. Archivado desde el original el 5 de septiembre de 2010 . Consultado el 10 de febrero de 2010 .
  28. ^ "Extensiones del lenguaje Clang: documentación de Clang 3.5". Clang.llvm.org. Archivado desde el original el 24 de febrero de 2014 . Consultado el 16 de abril de 2014 .
  29. ^ "Objective-C 2.0: más pistas". Listas.apple.com. 10 de agosto de 2006. Archivado desde el original el 18 de junio de 2009 . Consultado el 30 de mayo de 2010 .
  30. ^ "Re: Objetivo-C 2.0". Listas.apple.com. Archivado desde el original el 24 de noviembre de 2010 . Consultado el 30 de mayo de 2010 .
  31. ^ ab "Serie de lanzamientos de GCC 4.6: cambios, nuevas funciones y correcciones: Proyecto GNU: Free Software Foundation". Gcc.gnu.org . Archivado desde el original el 5 de enero de 2018 . Consultado el 24 de diciembre de 2017 .
  32. ^ abcd "Preguntas frecuentes sobre ObjC2". Paso GNU . Consultado el 6 de enero de 2020 .
  33. ^ "Navegador de origen: objc4, 756.2". Código abierto de Apple . Consultado el 6 de enero de 2020 .
  34. ^ Guía de programación de recolección de basura: API de recolección de basura Archivado el 9 de junio de 2012 en Wayback Machine (sitio web para desarrolladores de Apple: busque "__strong")
  35. ^ "Guía de programación de recolección de basura: Introducción a la recolección de basura". Apple Inc. 3 de octubre de 2011. Archivado desde el original el 9 de junio de 2012 . Consultado el 23 de diciembre de 2011 .
  36. ^ "Serie de tecnología Leopard para desarrolladores: descripción general de Objective-C 2.0". Apple Inc. 6 de noviembre de 2007. Archivado desde el original el 24 de julio de 2010 . Consultado el 30 de mayo de 2010 .
  37. ^ "Transición a las notas de la versión ARC". Apple Inc. 17 de julio de 2012. Archivado desde el original el 9 de junio de 2012 . Consultado el 26 de agosto de 2012 .
  38. ^ Mike ceniza. "Preguntas y respuestas del viernes 27 de septiembre de 2013: ARM64 y tú". mikeash.com. Archivado desde el original el 26 de abril de 2014 . Consultado el 27 de abril de 2014 .
  39. ^ "Hamster Emporium: [explicación del objeto]: isa sin puntero". Sealiesoftware.com. 24 de septiembre de 2013. Archivado desde el original el 3 de junio de 2014 . Consultado el 27 de abril de 2014 .
  40. ^ Apple, Inc. (2009). "Enumeración rápida". apple.com. Archivado desde el original el 17 de diciembre de 2009 . Consultado el 31 de diciembre de 2009 .
  41. ^ Fundación de Software Libre, Inc. (2011). "Serie de lanzamientos de GCC 4.6: cambios, nuevas funciones y correcciones". Gcc.gnu.org . Archivado desde el original el 2 de diciembre de 2013 . Consultado el 27 de noviembre de 2013 .
  42. ^ "Temas de programación de bloques: biblioteca para desarrolladores de Mac". Apple Inc. 8 de marzo de 2011. Archivado desde el original el 9 de junio de 2012 . Consultado el 28 de noviembre de 2012 .
  43. ^ ab "Recuento automático de referencias (ARC) de Objective-C - Documentación de Clang 11". Documentación clang . Consultado el 20 de febrero de 2020 . Por ahora, es sensato versionar este documento según las versiones de su única implementación (y su proyecto anfitrión), clang. "LLVM XY" se refiere a una versión de código abierto de clang del proyecto LLVM. "Apple XY" se refiere a una versión proporcionada por Apple del compilador LLVM de Apple.
  44. ^ "Transición a ARC". Apple Inc. Archivado desde el original el 7 de septiembre de 2011 . Consultado el 8 de octubre de 2012 .
  45. ^ "Notas de la versión LLVM 3.0". lanzamientos.llvm.org .
  46. ^ ab "Programación con Objective-C: valores y colecciones". Apple Inc. Archivado desde el original el 7 de septiembre de 2011 . Consultado el 8 de octubre de 2012 .
  47. ^ "Notas de la versión de Clang 3.1". lanzamientos.llvm.org .
  48. ^ "Literales de Objective-C: documentación de Clang 3.5". Clang.llvm.org. Archivado desde el original el 6 de junio de 2014 . Consultado el 16 de abril de 2014 .
  49. ^ Guía del desarrollador de Rhapsody , AP Professional, 1997, págs. 76–84
  50. ^ "Compilador de objetos portátil". Usuarios.pandora.be. 1 de enero de 1970. Archivado desde el original el 2 de agosto de 2008 . Consultado el 30 de mayo de 2010 .
  51. ^ "Página de inicio de Breadbox Computer Company LLC". Archivado desde el original el 27 de julio de 2011 . Consultado el 8 de diciembre de 2010 .
  52. ^ "gcc/libobjc". GitHub . espejo gcc. 6 de enero de 2020 . Consultado el 6 de enero de 2020 . El tiempo de ejecución ha sido completamente reescrito en gcc 2.4. El tiempo de ejecución anterior tenía varios errores graves y estaba bastante incompleto.
  53. ^ "API de tiempo de ejecución GNU Objective-C". Usando GCC . Consultado el 6 de enero de 2020 .
  54. ^ "WinObjC en GitHub". GitHub . Archivado desde el original el 2 de diciembre de 2017 . Consultado el 13 de febrero de 2018 .
  55. ^ "Instalador GNUStep". Archivado desde el original el 17 de febrero de 2018 . Consultado el 14 de febrero de 2018 .
  56. ^ Apple, Inc. (22 de agosto de 2006). "Mac OS X Leopard – Xcode 3.0". apple.com. Archivado desde el original el 24 de octubre de 2007 . Consultado el 22 de agosto de 2006 .
  57. ^ "Transición a las notas de la versión ARC". Biblioteca para desarrolladores de iOS . Desarrollador.apple.com. Archivado desde el original el 7 de septiembre de 2011 . Consultado el 16 de abril de 2014 .

Otras lecturas

enlaces externos