miércoles, 4 de enero de 2012

Objective-C

Objetive-C
Este libro tiene como propósito introducirle a los conceptos fundamentales de la programación
de el sistema Mac utilizando Xcode y Objective-C.
No se requiere experiencia previa en programación.


Introducción


Apple te ofrece todas las herramientas necesarias para desarrollar aplicaciones basadas en Cocoa, de forma gratuita. Este conjunto de herramientas, conocido con el nombre de Xcode, viene incluido con Mac OS X, o puedes bajarlo de la sección de desarrolladores en el sitio web de Apple.
Existen varios buenos libros sobre programación para Mac, pero asumen que ya tienes experiencia en programación. Este libro no. Se enseñan los conceptos básicos de programación, en particular con Objective-C, usando Xcode. Después de unos 5 capítulos, serás capaz de crear un programa básico, sin una interfaz gráfica de usuario (GUI). Después de unos capítulos más, sabrás cómo crear programas sencillos con un GUI. Cuando hayas terminado de leer este folleto, estarás listo para utilizar libros más avanzados. Tendrá que estudiar esos libros también, porque hay mucho más que aprender. Por ahora, sin embargo, no te preocupes porque este libro toma las cosas con calma.

Cómo usar este libro

Como podrás observar, algunos párrafos se muestran en un recuadro como el siguiente:
puntos técnicos
Te sugerimos leer cada capítulo dos veces (por lo menos). La primera vez pasa la caja de texto. La segunda vez que leas los capítulos incluye la caja de texto. Vas a ensayar en la práctica lo que has aprendido y aprenderás algunos puntos técnicos interesantes que hubieran sido distracciones la primera vez. Al utilizar el libro de esta manera, lograrás que la inevitable curva de aprendizaje sea una suave pendiente.
Este libro contiene docenas de ejemplos, que constan de una o más líneas de código de programación. Para asegurarse de que asocies una explicación a su respectivo ejemplo, cada ejemplo tiene la etiqueta de un número colocado entre corchetes, de esta manera: [1]. La mayoría de los ejemplos tienen dos o más líneas de código. A veces, un segundo número se utiliza para referirse a una determinada línea. Por ejemplo, [1.1] se refiere a la primera línea del ejemplo [1]. En los fragmentos largos de código, ponemos la referencia después de una línea de código, de esta manera:
//[1]
volumen = base * altura;      // [1.1]
La programación no es un trabajo simple . Se requiere un poco de perseverancia y que tú mismo trates de hacer todas las cosas que se enseñan en este libro. No se puede aprender a tocar el piano o conducir un coche exclusivamente por la lectura de libros. Lo mismo vale para aprender a programar. Este libro está en un formato electrónico, por lo que no tienes ninguna excusa para utilizar Xcode con frecuencia. Por lo tanto, a partir del capítulo 5, te sugerimos que vayas a través de cada capítulo en tres ocasiones. La segunda vez, prueba los ejemplos y haz pequeñas modificaciones al código para explorar cómo funcionan las cosas.

Antes de empezar

Escribimos este libro para usted. Como es gratis, por favor permítame decir un par de palabras sobre la promoción de la Mac a cambio. Cada usuario de Macintosh puede ayudar a promover su plataforma preferida con un poco esfuerzo. Aquí es cómo.
Cuanto más eficiente con la Mac sea usted, más fácil es llevar a otras personas a considerar una Mac. Por lo tanto, tratar de estar al día visitando sitios web orientados a la Mac y leer revistas de Mac. Por supuesto, el aprendizaje de Objective-C o AppleScript y ponerlos en uso es bueno tambien. Para las empresas, el uso de AppleScript puede ahorrar toneladas de dinero y tiempo. Echa un vistazo al folleto gratis de Bert, AppleScript Absolutos para Principiantes, disponible en:
Muestrale al mundo que no todo el mundo está usando una PC, haciendo la Macintosh más visible. El uso de una camiseta en público con el logo de Mac es una manera, pero hay otras maneras, puede hacer que el Mac sea más visibles dentro de su hogar. Si ejecuta Activity Monitor (en la carpeta Utilidades, que se encuentra en la carpeta de Aplicaciones de tu Mac), te darás cuenta de que tu Mac utiliza todo su poder de procesamiento sólo de vez en cuando. Los científicos han puesto en marcha varios proyectos de informática distribuida (DC) , como el Folding@home o SETI@home, que aprovechar esta potencia de procesamiento no utilizada, por lo general en pro del bien común.
Usted descarga un pequeño programa gratuito, llamado DC client, y empezara a procesar unidades de trabajo. Estos clientes DC correr con menor nivel de prioridad. Si estás usando un programa en tu Mac y las necesidades del programa requieren plena potencia de procesamiento, el DC client inmediatamente toma menor prioridad. Así, usted no notará que está funcionando. ¿Cómo ayuda esto a las Mac? Bueno, la mayoría de los proyectos DC mantienen rankings en sus sitios web de las unidades procesadas hasta la fecha. Si se inscribe en un equipo Mac (reconocerá sus nombre en los rankings), puede ayudar al equipo Mac de su elección para ascender en la clasificación. Así, los usuarios de otras plataformas de ordenador veran que tan bien las Macs están haciendo. Hay DC clients que se concentran en varios temas, como matemáticas, curar enfermedades y mucho más. Para elegir un proyecto DC que te gusta, echa un vistazo a:
Un problema con esta sugerencia: Se puede llegar a ser adicto!
Asegúrese de que la plataforma Macintosh tiene el mejor software. No, no sólo mediante la creación de programas propios. Haga un hábito de dar (cortés) retroalimentación a los desarrolladores de programas que usted utiliza. Incluso si trató una pieza de software y no le gusto, expliquele al desarrollador por qué. Asegúrese de informar sobre errores y proporcione una descripción exacta como sea posible de las acciones que realizó cuando se experimentó el error.
Pagar por el software que usted utiliza. Mientras el mercado de software para Macintosh sea viable, los desarrolladores seguirán proveyendo buen software.
Póngase en contacto con al menos 3 usuarios de Macintosh que podrían estar interesados en programación, digales acerca de este libro y dónde encontrarlo. O asesorelos sobre los 4 puntos mencionados arriba.
OK, mientras el DC client termina de descargar en el fondo, vamos a empezar!

Un programa es una serie de instrucciones

Presentación

Para conducir un automóvil, tienes que aprender a controlar varias cosas a la vez. La programación también requiere que mantengas un montón de cosas en mente, o tu programa romperá. Mientras que al menos ya conocías el interior de un coche antes de aprender a conducir, no tendrás esa ventaja cuando trates de aprender a programar con Xcode. Para no abrumarte, dejamos el entorno de programación para un capítulo posterior. En primer lugar, vamos a hacer que te sientas cómodo con algunos conceptos de Objective-C, empezando por la matemática básica.
En la escuela primaria había que hacer cálculos, rellenando los puntos:
2 + 6 = ……..
…….. = 3 * 4 (el asterisco * es la forma estándar para representar la multiplicación en los teclados de ordenador)
En la escuela secundaria, los puntos pasaron de moda y unas variables llamadas 'x' e 'y' (y una nueva palabra: "álgebra") fueron la gran sensación. Mirando hacia atrás, puede que te preguntes por qué nos hemos sentido tan intimidados en su momento por este pequeño cambio en la notación.
2 + 6 = x
y = 3 * 4

Variables

Objective-C también utiliza variables. Las variables no son nada más que nombres para referirse a unos datos concretos, como por ejemplo un número. Aquí tenemos una sentencia Objective-C, es decir, una línea de código, en la que asignamos un valor a una variable.
//[1]
x = 4;

El punto y coma

Se le ha asignado el valor 4 a la variable x. Te habrás dado cuenta de que hay un punto y coma al final de la instrucción. Esto se debe a que se requiere que todas las instrucciones terminen en punto y coma. ¿Por qué? Bien, el trozo de código que hay en el ejemplo [1] puede parecerte sencillo, pero un ordenador no es capaz de comprenderlo. Se necesita un programa especial, llamado compilador, para convertir ese texto en una secuencia de instrucciones que él sí sea capaz de entender y ejecutar. Leer y entender nuestro idioma puede ser muy difícil para un compilador así que debemos darle algunas pistas, por ejemplo: indicarle dónde termina cada sentencia; y eso es lo que hacemos con el punto y coma.
Si te olvidas el punto y coma en tu código, éste no se podrá compilar, es decir, no se va a poder convertir en un programa que tu Mac pueda ejecutar. No te preocupes ahora de eso, pues el compilador se quejará si hay algún problema y, como veremos en un capítulo posterior, intentará ayudarte a encontrar lo que esté mal.

Dar nombres a las variables

Mientras que los nombres de las variables no tienen una importancia especial para el compilador, el utilizar nombres descriptivos sí que nos puede facilitar la lectura del programa y hacerlo más comprensible. Ten esto en cuenta para cuando tengas que buscar errores en tu código.
Por tradición se llaman "bugs" (bichos) a los errores de los programas. A la búsqueda y reparación de bugs se le llama debugging (en español solemos decir depuración).
Por tanto, en programas reales evitaremos usar nombres de variables no descriptivos tales como x. Por ejemplo, el nombre de la variable en la que almacenaríamos el ancho de un dibujo sería anchoDibujo [2].
//[2]
anchoDibujo = 8;
Ahora que sabes que para el compilador es un gran problema que te olvides del punto y coma, comprenderás que en la programación hay que prestar atención a los detalles. Uno de esos detalles es que el código es sensible a mayúsculas/minúsculas. Es decir, la variable anchoDibujo no es la misma queanchoDIBUJO ni que AnchoDibujo. La convención que vamos a seguir para los nombres de variables es unir varias palabras, la primera iniciada por minúsculas y el resto por mayúsculas, tal como has visto en el ejemplo [2]. A este estilo se le suele llamar camelCase (se llama así por las jorobas del camello, en inglés camel. Cada mayúscula es una joroba). Te será conveniente seguir este esquema para reducir las posibilidades de cometer errores con los nombres de variables.
Ten en cuenta que los nombres de variables consisten en una sola palabra, en el sentido de que no hay espacios en el nombre.
Tienes total libertad para elegir el nombre de tus variables, pero hay una serie de reglas que debes seguir: la primera es que no puede ser el nombre de una palabra reservada de Objective-C (palabras que tienen un significado especial para Objective-C). Si tus variables están compuestas al menos de dos palabras unidas, como por ejemplo anchoDibujo, no vas a tener problema. Para facilitar la lectura se recomienda poner en mayúscula la inicial de cada palabra excepto la primera, tal como hemos visto. Sigue este esquema para evitar bugs en tus programas.
Si no te importa aprender un par de reglas más, sigue leyendo. También se permite el uso de dígitos además de letras, pero no puedes usar un dígito al comienzo del nombre. También se permite el guión bajo: "_". Vamos a ver ejemplos de nombres de variables.
    Nombres válidos de variables:
  • puerta8k
  • pu3rta
  • puer_ta
    Nombres no permitidos:
  • puerta 8 (porque contiene un espacio)
  • 8puerta (porque empieza por un dígito)
    Nombres válidos pero no recomendados:
  • Puerta8 (porque empieza por mayúscula)

Uso de variables en cálculos

Ahora que sabemos como asignar un valor a una variable, podemos hacer cálculos. Echemos un vistazo al código para calcular la superficie de un dibujo [3].
//[3]
anchoDibujo=8;
altoDibujo=6;
areaDibujo=anchoDibujo*altoDibujo;
Sorprendentemente, al compilador no le importan los espacios (con la excepción, como ya sabemos, de que están prohibidos en los nombres de variables), así que podemos usar todos los que queramos para facilitar la lectura de nuestro código.
//[4]
anchoDibujo = 8;
altoDibujo = 6;
areaDibujo = anchoDibujo * altoDibujo;
Y en un arranque de generosidad, el compilador también nos permite introducir saltos de línea en medio de las instrucciones ¿te imaginas por qué? Pues porque, si recuerdas lo que vimos un poco más arriba, él va a interpretar todo como una sola instrucción hasta que encuentre el punto y coma (el indicador de fin de instrucción). Podemos usar esta característica para facilitar la lectura en líneas excesivamente largas. Así que lo siguiente también sería válido para el compilador (pero también bastante incómodo de leer):
 
anchoDibujo =
   8;
altoDibujo
   = 6;
areaDibujo =
         anchoDibujo
        *
           altoDibujo;

Enteros y fraccionarios

Echemos un vistazo al ejemplo [5], especialmente a las dos primeras sentencias.
//[5]
anchoDibujo = 8;
altoDibujo = 4.5;
areaDibujo = anchoDibujo * altoDibujo;
Se pueden distinguir en general dos tipos de números: enteros y fraccionarios. Puedes ver un ejemplo de cada en [5.1] y [5.2] respectivamente. Los enteros se usan para contar, que es algo que haremos cuando queramos realizar una serie de instrucciones un número determinado de veces (ver capítulo 7). Los números fraccionarios los usamos, por ejemplo, con los precios.
Importante: Según el país, se usa como carácter separador de la parte decimal el punto "." o la coma ",". En Objective-C debemos emplear obligatoriamente siempre el punto.
El código del ejemplo [5] no funcionaría. El problema es que el compilador necesita que le indiques previamente el nombre de las variables que vas a usar en tu programa y también qué tipo de dato va a contener cada una. Eso es lo que llamamos "declarar una variable".
//[6]
int anchoDibujo;  // [6.1]
float altoDibujo, areaDibujo;  // [6.2]
anchoDibujo = 8;
altoDibujo = 4.5;
areaDibujo = anchoDibujo * altoDibujo;
En la línea [6.1], int indica que la variable anchoDibujo contiene un número entero. En la siguiente línea [6.2] declaramos dos variables con una sola instrucción, separando sus nombres con coma. En la sentencia también se indica que son de tipo float, lo que quiere decir que van a ser números con una parte fraccionaria. Llegados a este punto, parece que no tiene sentido que la variable anchoDibujo sea de tipo diferente a las otra dos. Pero lo que sabes es que si multiplicas un int por un float el resultado del cálculo es un float, que es la razón por la que deberías declarar la variable areaDibujo como float[6.2].
¿Por qué quiere el compilador conocer si una variable representa a un número entero o a uno fraccionario? Bien, un programa usa parte de la memoria del ordenador y el compilador reserva espacio para cada variable que se declara, pero necesita saber el tipo, ya que cada tipo requiere una cantidad distinta y también se representa de forma distinta en la memoria del ordenador.
¿Y si necesitamos trabajar con números muy grandes o con gran precisión de decimales? ¿Van a poder representarse en los tipos que conocemos hasta ahora (int y float)? Bien, esta pregunta tiene dos respuestas: en primer lugar, existen otros tipos de datos para enteros más grandes (long) y para fraccionarios de más precisión (double). Pero incluso estos tipos de dato podrían no ser suficiente, lo que nos lleva a la segunda respuesta: como programador, parte de tu trabajo es estar atento a los posibles problemas. Pero eso no es un asunto para discutir en el primer capítulo de un libro de introducción.
Por cierto, los tipos que hemos visto pueden almacenar también números negativos. Si sabes que el valor de tu variable nunca va a ser negativo puedes restringir el rango de valores.
//[7]
unsigned int cajasDisponibles;
No tiene sentido que el número de cajas disponibles en el almacén sea negativo, así que en este caso podríamos usar unsigned int. El tipo unsigned int representa un número entero mayor o igual a cero.

Declarar variables

Es posible declarar una variable y asignarle un valor de una vez [8].
//[8]
int x = 10;
float y= 3.5, z = 42;
Esto te ahorra algo de tecleo.

Tipos de datos

Como ya hemos visto, los datos almacenados en variables pueden ser de varios tipos específicos, por ejemplo int o float.
En Objective-C, a los tipos de dato como esos se les llama también tipos escalares. A continuación mostramos una lista con los tipos de dato escalares más comunes de Objective-C:
NombreTipoEjemplo
voidVacíoNada
intNúmero entero...-1, 0, 1, 2...
unsignedNúmero entero positivo0, 1, 2...
floatNúmero fraccionario-0.333, 0.5, 1.223, 202.85556
doubleNúmero fraccionario de doble precisión0.52525252333234093890324592793021
charCarácterhola
BOOLBoolean0, 1; TRUE, FALSE; YES, NO.

Operaciones matemáticas

En los ejemplos previos hemos realizado una multiplicación. Se usan los siguientes símbolos, conocidos oficialmente como "operadores", para realizar cálculos matemáticos básicos.
+  suma
-  resta
/  división
*  multiplicación
Aparte de estos operadores, si echamos un vistazo al código de un programa en Objective-C, podemos encontrarnos con un par de curiosidades, quizá porque los programadores son unos mecanógrafos perezosos.
En lugar de escribir x = x + 1;, con frecuencia los programadores recurren a cosas como [9] y [10]
//[9]
x++;

//[10]
++x;
En cualquiera de los dos casos, lo que significa es: incrementa en 1 el valor de x. En algunas circunstancias es importante situar el ++ antes o después del nombre de la variable. Fíjate en estos ejemplos [11] y [12].
//[11]
x = 10;
y = 2 * (x++);
// "x" tiene aquí el valor 11, pero se le asignó DESPUES de realizar el cálculo
// por tanto "y" tiene el valor 20

//[12]
x = 10;
y = 2 * (++x);
// "x" también vale ahora 11, pero su valor se asignó ANTES de hacer el cálculo
// así que "y" vale 22
Si usamos el ++ antes del nombre de la variable, se incrementará su valor antes de emplear la variable en el cálculo en el que esté envuelta. Si usamos ++ después del nombre de la variable, se incrementará su valor después de utilizarse en el cálculo en el que esté envuelta. El código de [12] es equivalente al de [13].
//[13]
x = 10;
x++;  // [13.2]
y = 2 * x;
// Como el incremento de x en la línea [13.2] no está envuelto en ninguna
// operación, en este caso sería lo mismo usar ++x que x++
 
Con esto se unen dos sentencias en una, pero quizá pueda hacer un poco más difícil de entender tu programa. Es correcto emplearlo pero ten en cuenta que puede estar acechando un bug por ahí.

Paréntesis

Seguro que ya lo sabes, pero los paréntesis se pueden utilizar para indicar el orden en el que queremos que se realicen las operaciones. La multiplicación y división tienen precedencia sobre la suma y la resta, así que, por ejemplo, 2 * 3 + 4 es igual a 10. Usando paréntesis podemos forzar a que se realice antes la suma que la multiplicación: 2 * (3 + 4) es igual a 14.

División

La división requiere un poco de atención, ya que tiene un comportamiento distinto según usemos enteros o fraccionarios. Echa un vistazo a los ejemplos [14] y [15].
//[14]
int x = 5, y = 12, ratio;
ratio =  y / x;

//[15]
float x = 5, y = 12, ratio;
ratio =  y / x;
En el primer caso [14], el resultado es 2 ¿Por qué? Al ser enteros el dividendo y el divisor, el resultado también es un número entero. En el segundo [15], el resultado es el que probablemente te esperas: 2,4

Booleanos

Un booleano (la palabra viene de George Boole, el matemático inventor de la lógica booleana) es un valor lógico verdadero o falso. Se pueden considerar equivalentes el 1 como valor verdadero y el 0 como valor falso.
VerdaderoFalso
10
Se emplean con frecuencia para determinar si se realiza o no una acción dependiendo del valor booleano de alguna variable o función.

Resto (en inglés: modulus)

Probablemente no estés tan familiarizado con el operador %, que no tiene que ver con los porcentajes sino que calcula el resto de la división entre el primer y el segundo operando (si el segundo operando es 0, el comportamiento de % es indefinido).
//[16]
int x = 13, y = 5, resto;
resto =  x % y;
La variable resto contendrá el valor 3.
Más ejemplos de este operador:
21 % 7 es igual a 0
22 % 7 es igual a 1
23 % 7 es igual a 2
24 % 7 es igual a 3
27 % 7 es igual a 6
30 % 2 es igual a 0
31 % 2 es igual a 1
32 % 2 es igual a 0
33 % 2 es igual a 1
34 % 2 es igual a 0
50 % 9 es igual a 5
60 % 29 es igual a 2
Puede sernos útil en ocasiones, pero ten en cuenta que sólo funciona con enteros.
Uno de los usos más comunes del operador % es determinar si un número es par o impar. Si es par, su resto entre 2 es 0, si es impar entonces será 1. Por ejemplo:
//[17]
int unNumero;
//Aquí escribiríamos código que asigna un valor a "unNumero"
if ((unNumero % 2) == 0) // [17.3]
  {
    NSLog(@"unNumero es par");
  }
  else
  {
    NSLog(@"unNumero es impar");
  }
En la línea [17.3] se ha empleado un condicional, que verás en el capítulo 6. Podríamos traducir la instrucción como: "si el resto de la división unNumero entre 2 es igual a 0, entonces …"

Sin comentarios? Inaceptable!

Introducción

Si utilizamos nombres de variables con sentido, haremos que nuestro código sea más legible y entendible [1].
//[1]
float anchoDelDibujo, altoDelDibujo, areaDelDibujo;
anchoDelDibujo = 8.0;
altoDelDibujo = 4.5;
areaDelDibujo = anchoDelDibujo * altoDelDibujo;
Hasta ahora nuestros ejemplos de código han sido de sólo unas pocas sentencias, pero incluso los programas más sencillos pueden crecer rápidamente hasta cientos o miles de líneas. Cuando revises tu programa después de algunas semanas o meses puede ser difícil recordar la razón por la que tomaste ciertas decisiones. Ahí es donde entran en acción los comentarios. Los comentarios ayudarán a comprender rápidamente lo que hace cada parte de tu programa y por qué. Algunos programadores van más allá y siempre comienzan a codificar cada clase como comentarios, con lo que se organizan mejor y evitan tener que improvisar código posteriormente.
Recomendamos invertir tiempo en comentar el código. Podemos asegurarte que esa inversión será revertida con creces en el futuro. También, si compartes tu código con alguien más, tus comentarios ayudarán a que se adapte a tus propias necesidades más rápidamente.

Crear comentarios

Para indicar el comienzo de un comentario teclea dos barras.
// Esto es un comentario
En Xcode los comentarios se muestran en verde. Si el comentario es largo y ocupa varias líneas, enciérralo entre /* */.
/* This is a comment
extending over two lines */

Comentar código

Hablaremos sobre la depuración dentro de poco, ya que Xcode tiene buenas herramientas para ello. Una de las formas de depuración a la vieja usanza es comentar el código. Comentamos código envolviendo las instrucciones entre /* */, de esta forma deshabilitamos el código, impidiendo su ejecución y podemos comprobar si el resto funciona como esperábamos. Esto puede ayudarnos a encontrar errores. Si, por ejemplo, la parte de código comentada asigna valores a una variable, podemos añadir una línea de código temporal que asigne a esa variable un valor que nos sirva para comprobar el resto de nuestro código.

¿Por qué incluir comentarios?

No debemos desestimar la importancia de los comentarios. Frecuentemente es útil incluir explicaciones en nuestro idioma sobre lo que hace una serie de instrucciones. Así no hay que estar deduciendo qué es lo que hace esa parte de código y podemos darnos cuenta inmediatamente de si el problema tiene su origen o no en esa sección. Además podemos usar los comentarios para explicar cosas difíciles o casi imposibles de deducir leyendo el código. Por ejemplo, si programas una función matemática que encontraste detallada en un libro, podrías poner la referencia bibliográfica dentro de un comentario.
A veces es útil hacer los comentarios antes de escribir el código. Eso ayudará a estructurar tus pensamientos y como resultante la programación será mas fluida.
Los ejemplos de código que encontrarás en este libro no contienen tantos comentarios como generalmente se deberían poner, pero eso es porque ya se dan las explicaciones en el texto que los precede.

Funciones

Introducción

El trozo de código más largo que hemos visto hasta ahora tenía sólo cinco líneas. Los programas de varias miles de líneas parecen quedarnos aún muy lejos, pero debido a la naturaleza de Objective-C, debemos discutir la forma de organizar los programas en esta etapa temprana.
Si un programa consistiese en una sucesión larga y continua de instrucciones sería difícil encontrar y reparar errores. Además, una serie concreta de instrucciones podría aparecer en varias partes de tu programa. Si hubiese en ellas algún error, deberías arreglar el mismo error en varios lugares. Eso sería una pesadilla porque sería fácil olvidarse de uno (o varios). Por tanto, la gente ha pensado una solución para organizar el código, facilitando la corrección de errores.
La solución a este problema es agrupar las instrucciones dependiendo de la tarea que realicen. Por ejemplo, tienes una serie de instrucciones que calculan el área de un círculo. Una vez que has comprobado que esas instrucciones funcionan correctamente, nunca tendrás que volver a ese código para examinar si hay algún error en él. El conjunto de instrucciones, llamado función (function en inglés), tiene un nombre y puedes llamarlo por ese nombre cada vez que necesites que se ejecute ese código. Este concepto de usar funciones es fundamental, de hecho siempre hay al menos una función en un programa: la función main(). Esta función main() es la que busca el compilador para saber por donde debe empezar la ejecución del programa.

La función main()

Pasemos a estudiar la función main() con más detalle. [1]
//[1]
main()
{
    // Cuerpo de la función main(). Escribe aquí tu código.
}
La sentencia [1.1] muestra el nombre de la función, en este caso "main", seguido de la apertura y cierre de paréntesis. Es obligatorio que exista esta función main(), que por otro lado es una palabra reservada (lo que significa entre otras cosas que no podemos usarla como nombre para nuestras variables). Cuando creemos nuestras funciones podremos darles el nombre que queramos. Los paréntesis están ahí por una buena razón, pero la conoceremos más adelante en este capítulo. En las siguiente líneas [1.3, 1.5], hay llaves. Debemos poner nuestro código entre esas llaves { }. Cualquier cosa entre las llaves es lo que llamamos el cuerpo de la función. He copiado código del primer capítulo y lo he puesto aquí en donde corresponde [2].
//[2]
main()
{
    // A continuación se declaran las variables
    float anchoDelDibujo, altoDelDibujo, superficieDelDibujo;
    // Asignamos un valor inicial a las variables
    anchoDelDibujo = 8.0;
    altoDelDibujo = 4.5;
    // Aquí se realiza el cálculo
    superficieDelDibujo = anchoDelDibujo * altoDelDibujo;
}

Nuestra primera función

Si escribimos todo nuestro código en el cuerpo de la función main(), eso nos llevaría al problema del código desestructurado y difícil de depurar que queremos evitar. Así que escribamos otro programa, ahora con un poco de estructura. Además de la función main() obligatoria crearemos una funcióncalculaAreaDelCirculo() [3].
//[3]
main()
{
    float anchoDelDibujo, altoDelDibujo, superficieDelDibujo;
    anchoDelDibujo = 8.0;
    altoDelDibujo = 4.5;
    superficieDelDibujo = anchoDelDibujo * altoDelDibujo;
}
calculaAreaDelCirculo()   // [3.9]
{
}
Ha sido fácil, pero nuestra función definida desde la línea [3.9] aún no hace nada. Observa que la especificación de la función está fuera del cuerpo de la función main(). En otras palabras, las funciones no están anidadas.
Queremos que nuestra nueva función calculaAreaDelCirculo() sea llamada desde la función main(). Veamos cómo podemos hacerlo [4].
//[4]
main()
{
    float anchoDelDibujo, altoDelDibujo, superficieDelDibujo,
        radioDelCirculo, superficieDelCirculo;  // [4.4]
    anchoDelDibujo = 8.0;
    altoDelDibujo = 4.5;
    radioDelCirculo = 5.0; // [4.7]
    superficieDelDibujo = anchoDelDibujo * altoDelDibujo;
    // ¡Aquí es donde llamamos a nuestra función!
    superficieDelCirculo = calculaAreaDelCirculo(radioDelCirculo); // [4.10]
}
Nota: no mostramos el resto del programa (ver [3]).

Pasar argumentos a la función

Hemos añadido un par de nombres de variable de tipo float [4.4], y hemos inicializado la variableradioDelCirculo dándole un valor [4.7].
Tiene más interés la línea [4.10], en la que llamamos a la función calculaAreaDelCirculo(). Como puedes ver, el nombre de la variable radioDelCirculo se ha puesto entre paréntesis. Es un argumento de la función calculaAreaDelCirculo(). El valor de la variable radioDelCirculo se pasa a la funcióncalculaAreaDelCirculo(). Cuando la función calculaAreaDelCirculo() ha hecho su tarea debe devolver un valor, en este caso el resultado del cálculo de la superficie. Modifiquemos el código de la función calculaAreaDelCirculo() [5].
Nota: sólo se muestra el código de la función calculaAreaDelCirculo().
//[5]
calculaAreaDelCirculo(float radio) // [5.1]
{
    float area;
    area = 3.1416 * radio * radio;  // pi veces el cuadrado del radio [5.4]
    return area;
}
En [5.1] definimos que se requiere un valor de tipo float como entrada para la funcióncalculaAreaDelCirculo(). Cuando se recibe, ese valor es almacenado en una variable llamada radio. Usamos una segunda variable, area, para almacenar el resultado del cálculo en [5.4], así que la declaramos en [5.3] de la misma forma que hemos declarado variables en la función main() [4.4]. Verás que la declaración de la variable radio se ha hecho dentro de los paréntesis [5.1]. La línea [5.5] devuelve el resultado a la parte del programa desde la que fue llamada esta función. Como consecuencia, en la línea [4.10], se asigna ese valor a la variable superficieDelCirculo.
La función en el ejemplo [5] está completa, excepto por una cosa. No hemos especificado el tipo de datos que devolverá la función. El compilador nos va a requerir ese dato, así que no nos queda otra opción que obedecerle e indicar que es de tipo float [6.1].
//[6]
float calculaAreaDelCirculo(float radio)  //[6.1]
{
    float area;
    area = 3.1416 * radio * radio;
    return area;
}
Como indica la primera palabra de la línea [6.1], el dato devuelto por esta función (en este caso el dato devuelto por la variable area), es de tipo float. Como programador, debes asegurarte de que la variablesuperficieDelCirculo en la función main() es también de ese tipo, para que el compilador no nos moleste sobre ese asunto.
No todas las funciones requieren argumentos. Si no hay ninguno, los paréntesis siguen siendo obligatorios, aunque no tengan contenido.
//[7]
int tiraElDado()
{
    int numeroDePuntos;
    // Aquí se escribiría código para generar un número aleatorio entre 1 y 6
    return numeroDePuntos;
}

Devolución de valores

No todas las funciones devuelven un valor. Si una función no devuelve un valor, entonces es de tipo void(que significa "vacío"). En este caso, la sentencia return es opcional. Si la usas, entonces la palabrareturn debe ir sola, sin indicarle a continuación un valor o nombre de variable.
//[8]
void alarmaXVeces(int x);
{
    // Código para hacer que suene la alarma x veces
    return;
}
Si la función tiene más de un argumento, como en la función calculaAreaDelDibujo() que está a continuación, los argumentos van separados por comas (,).
//[9]
float calculaAreaDelDibujo(float ancho, float alto)
{
    // Código para calcular la superficie...
}
Por convenio, la función main() debería devolver un entero y, por tanto, debería tener también una sentencia return. Debería devolver 0 (cero, [10.9]) para indicar que todo se ha ejecutado sin problemas. Ya que devuelve un entero, debemos escribir int antes de main() [10.1]. Pongamos junto todo el código que tenemos.
//[10]
int main()  // [10.1]
{
    float anchoDelDibujo, altoDelDibujo, areaDelDibujo,
       radioDelCirculo, superficieDelCirculo;
    anchoDelDibujo = 8;
    altoDelDibujo = 4.5;
    radioDelCirculo = 5.0;
    areaDelDibujo =  anchoDelDibujo * altoDelDibujo;
    superficieDelCirculo = calculaAreaDelCirculo(radioDelCirculo);      // [10.8]
    return 0;      // [10.9]
}
float calculaAreaDelCirculo(float radio)           // [10.12]
{
    float area;  // [10.14]
    area = 3.1416 * radio * radio;
    return area;
}

Hacer que todo funcione

Como puedes ver en [10], tenemos una función main() y otra función que hemos definido nosotros mismos [10.12]. Si intentásemos compilar este código, el compilador lo rechazaría. En la línea [10.8] indicaría que no conoce ninguna función llamada calculaAreaDelCirculo(). ¿Por qué? Aparentemente el compilador comienza leyendo la función main() y de repente encuentra algo que desconoce. No va más allá y nos muestra este aviso. Para satisfacer al compilador, simplemente debemos añadir una declaración de función antes de la línea con el main() [11.1]. No tiene complicación, ya que es la misma línea que en [10.12] excepto que termina con punto y coma (;). Ahora el compilador no se llevará una sorpresa cuando se encuentre la llamada a esa función.
//[11]
float calculaAreaDelCirculo(float radio);  // [11.1] declaración de la función 
int main()
{
    // Aquí va el código de la función main...
}
Nota: no se muestra aquí el resto del programa (ver [10]).
En seguida compilaremos el programa en la realidad. Pero antes un par de comentarios.
Cuando escribas programas es importante que intentes tener en mente la posibilidad de reutilizar tu código en un futuro. Nuestro programa podría tener una función calculaAreaDelRectangulo() tal como la que se muestra a continuación [12], que podría llamarse desde la función main(). Esto sería útil incluso aunque sólo se llamase a esa función una vez. La función main() sería más fácil de leer. Si tuviéramos que depurar el código sería más fácil encontrar el error analizando cada función que siguiendo una larga secuencia de instrucciones.
//[12]
float calculaAreaDelRectangulo(float largo, float ancho)  // [12.1]
{
    return (largo * ancho); //[12.3]
}
Como puedes ver, en un caso simple como este, es posible agrupar en una sola instrucción el cálculo y la devolución del resultado [12.3]. En [10.14] usé la variable area simplemente para mostrar cómo declarar una variable dentro de una función.
Aunque las funciones que definimos en este capítulo son bastante sencillas, es importante darse cuenta de que se puede modificar el contenido de una función sin que ello afecte al código que la llama. Lo que no debe cambiarse es la declaración de la función (es decir, su primera línea).
Por ejemplo, podemos cambiar el nombre de las variables internas de la función y seguirá trabajando (y esto no influirá en el resto del programa). Alguien podría escribir la función y tú podrías utilizarla sin conocer su interior. Todo lo que necesitas es saber cómo usarla. Ello implica conocer:
  • el nombre de la función
  • el número, orden y tipo de cada argumento
  • Lo que devuelve la función y el tipo del resultado
En el ejemplo [12], esas respuestas son, respectivamente:
  • calculaAreaDelRectangulo
  • Dos argumentos, ambos de tipo float, siendo el primero el alto y el segundo el ancho.
  • La función devuelve la superficie, y el resultado es de tipo float (como podemos deducir de la primera palabra de la línea [12.1]).

Variables protegidas

El código de cada función está protegido del programa principal y de cualquier otra función.
Esto significa que el valor de una variable interna de una función por defecto no puede ser modificado por ninguna otra variable de ninguna otra función, incluso aunque tuvieran el mismo nombre. Esta es una característica esencial de Objective-C. En el capítulo 5 volveremos a discutir este comportamiento. Pero antes vamos a arrancar Xcode y ejecutar el programa anterior [10].

Salida en pantalla

Introducción

Hemos hecho grandes progresos con nuestro programa, pero aún no hemos visto como mostrar los resultados de nuestros cálculos. El lenguaje Objective-C por si mismo no sabe como hacerlo, pero por suerte podemos utilizar funciones que han escrito otros ya. Hay varias opciones para mostrar resultados por pantalla. En este libro usaremos una función incluida en el entorno Cocoa de Apple: la funciónNSLog(). Esto es estupendo, porque no tenemos que preocuparnos (ni tenemos que programar nada al respecto) para obtener nuestros resultados en la pantalla.
Así que ¿dónde muestra los datos NSLog()? En Xcode existe la Consola para visualizar los mensajes de log. Para abrir la Consola, debemos seleccionar [Console] desde el menú [Run] (Cmd-Shift-R). Una vez que construyamos y ejecutemos nuestra aplicación, todos los mensajes aparecerán por ahí.
La función NSLog() se diseñó para mostrar mensajes de error, no para los resultados de una aplicación. De todas formas es tan fácil de usar que la hemos adoptado en este libro para visualizar nuestros resultados. Una vez que conozcas Cocoa en profundidad descubrirás técnicas más sofisticadas para hacerlo.

Uso de NSLog

Veamos como usar la función NSLog() con el siguiente código:
//[1]
int main()
{
    NSLog(@"Julia es mi actriz favorita.");
    return 0;
}
Al ejecutarlo, se producirá la aparición del texto "Julia es mi actriz favorita" en la Consola. El texto entre @" y " (lo que está entre las comillas dobles) es lo que se llama "cadena de caracteres", "cadena de texto" o simplemente "cadena" (en inglés "string").
Además de ese texto, la función NSLog() muestra información adicional, como la fecha actual y el nombre de la aplicación. Por ejemplo, la salida completa del programa [1] en mi sistema es:
2010-03-12 22:12:38.052 prueba1[5006:a0f] Julia es mi actriz favorita.
Una cadena puede tener una longitud de cero o más caracteres.
Nota: en los siguientes ejemplos sólo se muestran las sentencias interesantes de la función main()
//[2]
NSLog(@""); //[2.1]
NSLog(@" "); //[2.2]
 
La sentencia [2.1] contiene 0 caracteres y la llamamos cadena vacía (tiene una longitud 0). La sentencia [2.2] no es una cadena vacía aunque lo parezca. Contiene un espacio entre las comillas así que su longitud es 1.
Hay algunas secuencias de caracteres que tienen un significado especial dentro de las cadenas. Se les llama "secuencias de escape".
Por ejemplo para hacer que la última palabra de nuestra cadena empiece en una línea nueva, debemos incluir un código especial en la sentencia [3.1]. El código es \n, que significa "carácter de nueva línea".
//[3]
NSLog(@"Julia es mi actriz \nfavorita.");
Ahora la salida tiene un aspecto como este (sólo se muestra el contenido relevante):
Julia es mi actriz
favorita.
La contrabarra (\) en [3.1] se llama carácter de escape, ya que indica a la función NSLog que el siguiente carácter no debe ser impreso directamente en pantalla sino que tiene un significado especial: en este caso la "n" significa "salta a la siguiente línea".
En el caso (no muy habitual) de que quisieras mostrar un contrabarra en pantalla, podría parecer que tienes un problema. Si el carácter tras la contrabarra tiene un significado especial, ¿cómo será posible imprimir una contrabarra?. Pues simplemente poniendo dos contrabarras juntas. Esto indicará a la función NSLog que debe imprimir la segunda contrabarra. Aquí tenemos un ejemplo:
//[4]
NSLog(@"Julia es mi actriz favorita.\\n");

La sentencia [4.1] producirá, tras la ejecución, la siguiente salida:
Julia es mi actriz favorita.\n

Mostrar variables

Hasta ahora sólo hemos mostrado cadenas estáticas. Imprimamos ahora el resultado de un cálculo.
//[5]
int x, numeroAMostrar;
x = 1;
numeroAMostrar = 5 + x;
NSLog(@"El valor del entero es %d.", numeroAMostrar);
Fíjate que, entre los paréntesis, tenemos una cadena, una coma y el nombre de una variable. La cadena contiene algo curioso: %d. Al igual que la contrabarra, el carácter de porcentaje (%) tiene un sentido especial. Si va seguido de una d (abreviatura para indicar número entero en sistema decimal), hace que en esa posición se inserte el valor que va a continuación de la coma, en este caso el contenido de la variable numeroAMostrar. Al ejecutar el ejemplo [5] el resultado será:
El valor del entero es 6.
Para mostrar un número con decimales (en inglés se llama tipo "float"), usaremos %f en lugar de %d.
//[6]
float x, numeroAMostrar;
x = 12345.09876;
numeroAMostrar = x/3.1416;
NSLog(@"El valor del número con decimales es %f.", numeroAMostrar);
Más tarde, cuando aprendas a hacer repeticiones de cálculos, podrías queres realizar una tabla de valores. Imagina una tabla de conversión de grados Fahrenheit a Celsius. Si quieres que los datos mostrados tengan buena apariencia, necesitarás que los datos en cada una de las dos columnas tengan un ancho fijo. Puedes especificar ese ancho introduciendo un número entero entre % y f (o entre % y dsegún el tipo de variable). Aún así, si el ancho que especificas es menor que el ancho del número, prevalecerá el ancho del número.
//[8]
int x = 123456;
NSLog(@"%2d", x);
NSLog(@"%4d", x);
NSLog(@"%6d", x);
NSLog(@"%8d", x);

La ejecución del ejemplo [8] producirá la siguiente salida:
123456
123456
123456
  123456
En las dos primeras sentencias [8.2, 8.3] solicitamos demasiado poco espacio para que el número sea mostrado completamente, pero se toma el espacio igualmente. Sólo en la sentencia [8.5] se especifica un ancho mayor que el del valor, y es donde apreciamos los espacios adicionales que se han requerido para mostrar el número.
También es posible combinar la especificación del ancho y el número de decimales con los que queremos que se muestre el dato.
//[9]
float x=1234.5678;
NSLog(@"Reserva espacio para 10, y muestra 2 dígitos significativos.");
NSLog(@"%10.2f", x);

Mostrar múltiples valores

Por supuesto es posible mostrar más de un valor o cualquier combinación de valores [10.3]. Lo que debes hacer es asegurarte de indicar correctamente el tipo de cada dato (intfloat), usando %d y %f.
//[10]
int x = 8;
float pi = 3.1416;
NSLog(@"El valor de x es %d, mientras que el valor de pi es %f.", x, pi);

Asignar los símbolos a los valores

Uno de los errores más comunes entre los principiantes es especificar incorrectamente el tipo en funciones como NSLog y otras. Si tus resultados no son los esperados o el programa rompe sin una razón, revisa las sentencias en las que asignas los tipos de dato.
Si es incorrecta la asignación del primer dato, puede que el segundo tampoco sea mostrado correctamente. Un ejemplo:
//[10b]
int x = 8;
float pi = 3.1416;
NSLog(@"El valor int es %f, mientras que el valor float es %f.", x, pi);
// Lo correcto sería : NSLog(@"El valor int es %d, mientras que el valor float es %f.", x, pi);
produce la siguiente salida por consola:
El valor int es 3.141600, y el float es nan.

Vincular con la librería Foundation

Estamos a solamente una pregunta y una respuesta de ejecutar nuestro primer programa.
¿Cómo hace nuestro programa para conocer la función NSLog()? Bien, realmente no la conoce, a menos que nosotros se lo digamos. Para hacerlo, tenemos que indicar al compilador que importe la librería en la que está implementada la función NSLog() (junto a otras muchas que iremos conociendo). La sentencia es la siguiente:
#import <Foundation/Foundation.h>
Ésta debe ser la primera sentencia en nuestro programa. Si juntamos todo lo que hemos aprendido en este capítulo obtendremos el siguiente código, que haremos funcionar en el siguiente capítulo.
//[11]
#import <Foundation/Foundation.h>
float calculaAreaDelCirculo(float radio);
float calculaAreaDelRectangulo(float ancho, float alto);
int main()
{
    float anchoDelDibujo, altoDelDibujo, areaDelDibujo,
        radioDelCirculo, areaDelCirculo;
    anchoDelDibujo  = 8.0;
    altoDelDibujo = 4.5;
    radioDelCirculo  = 5.0;
    areaDelDibujo = calculaAreaDelRectangulo(anchoDelDibujo, altoDelDibujo);
    areaDelCirculo = calculaAreaDelCirculo(radioDelCirculo);
    NSLog(@"Area del círculo: %10.2f.", areaDelCirculo);
    NSLog(@"Area del cuadrado: %f.", areaDelDibujo);
    return 0;
}
float calculaAreaDelCirculo(float radio)  // primera función personalizada
{
    float area;
    area = 3.1416 * radio * radio;
    return area;
}
float calculaAreaDelRectangulo(float ancho, float alto) // segunda función personalizada
{
    return ancho* alto;
}


Compilación y ejecución de un Programa

Introducción

El código que hemos escrito hasta ahora no es más que texto relativamente sencillo de leer para nosotros. No es que sea prosa precisamente, pero es aún peor para nuestro Mac. ¡No puede hacer nada con él! Se necesita un programa especial, llamado compilador, para convertir este texto en un conjunto de instrucciones que el Mac pueda entender y ejecutar. El compilador es parte de Xcode, el entorno de programación gratuito de Apple. Deberías haber instalado Xcode desde el disco que viene con la copia de Mac OS X. En cualquier caso, verifica que tienes la última versión, que puedes descargar enhttp://developer.apple.com (se requiere registro gratuito).

Crear un proyecto

Arranca Xcode, que encontrarás en /Developer/Applications. La primera vez te hará responder algunas preguntas. Acepta las sugerencias que él haga, en principio son adecuadas y además podrás modificarlas más adelante en el menú Preferencias. Para empezar realmente, selecciona New Project en el menú File. Aparece una ventana de diálogo con los tipos de proyecto disponibles. El aspecto puede variar ligeramente según la versión de Xcode.
01 New Project
El asistente de Xcode te permite crear nuevos proyectos.
En este momento queremos crear un programa simple en Objective-C, sin GUI (Interfaz gráfica de usuario), así que dentro de Command Line Tool selecciona Type Foundation.
02 New Title
Introduce un nombre para tu aplicación, como "justatry". Selecciona el lugar en el que quieres guardar tu proyecto y pulsa Finish.
El proyecto que estamos creando va a poder ejecutarse desde el Terminal (/Aplicaciones/Utilidades/Terminal). Si quieres evitarte molestias, asegúrate de que el nombre del proyecto consta de una sola palabra (sin espacios). También es costumbre que los nombres de programas que se ejecutan en terminal comiencen por minúscula. Por el contrario, los nombres de programas con interfaz gráfica suelen comenzar por mayúscula.

Explorando Xcode

A continuación se muestra una ventana que tú como programador verás con frecuencia. Tiene dos marcos principales a derecha e izquierda. El de la izquierda es "Groups & Files", desde el que accedemos a todos los elementos de los que consta nuestro proyecto. En este momento no hay demasiados, pero cuando creemos programas con interfaz gráfica (GUI) y multiidioma, aquí veremos todos los ficheros relacionados con la GUI y con los diferentes idiomas. Los ficheros se agrupan en carpetas, pero no busques esas carpetas en tu Mac con el Finder ya que son virtuales; aparecen aquí para organizar nuestro trabajo.
En el marco "Groups & Files" abre el grupo justatry (pulsando el triángulo gris que está a la izquierda de su nombre) y dentro de éste abre el grupo Source. Dentro encontrarás un fichero llamado justatry.m[1]. ¿Recuerdas que todo programa debe contener una función llamada main()? Bien, este es el fichero que contiene la función main(). Más tarde en este capítulo vamos a modificarla para incluir el código de nuestro programa. Si abres justatry.m te llevarás una sorpresa: Apple ha creado ya por ti la funciónmain().
03 Xcode Window
Xcode mostrando la función main().
//[1]
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) //[1.2]
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //[1.4]
  // insert code here...
  NSLog(@"Hello, World!");
  [pool drain]; //[1.7]
  return 0;
}
Echa un vistazo al código y busca elementos que puedas reconocer. Verás:
  • La sentencia import necesaria para poder utilizar funciones como NSLog().
  • La función main().
  • Las llaves entre las que debemos encerrar el código de nuestro programa.
  • Un comentario, que nos invita a escribir código en esa posición.
  • Una instrucción con NSLog(), para mostrar una cadena de texto en pantalla.
  • Una sentencia return 0;.
Pero también hay algunas cosas que no reconocemos:
  • Los argumentos que se le pasan a la función main(). [1.2]
  • Una línea que empieza por NSAutoreleasePool [1.4]
  • Otra línea que contiene las palabras pool y drain [1.7].
Personalmente no me gusta que los autores de libros me muestren a mi, como lector, código lleno de elementos desconocidos y me prometan que más adelante lo veré todo claro. Por eso he preferido explicar en capítulos anteriores lo que son las funciones, para que no te enfrentes ahora a demasiados conceptos nuevos.
Así que ahora ya sabes que las funciones son una forma de organizar el código, que todos los programas tienen una función main() y cual es el aspecto de las funciones. Aún así, debo admitir que por ahora no puedo explicar completamente todo lo que ves en el ejemplo [1]. Siento tener que pedirte que ignores lo que ves en [1.2, 1.4 y 1.7]. Antes debes familiarizarte con otros elementos de Objective-C. La buena noticia es que ya has pasado dos capítulos complicados y los tres siguientes son bastante llevaderos, antes de que tengamos que tratar de nuevo con cuestiones complejas.
Si realmente no aguantas sin una explicación, aquí va un resumen.
Los argumentos que se pasan a la función main() son necesarios para poder ejecutar el programa en el Terminal.
Los programas necesitan memoria para funcionar y deben dejarla a disposición del resto cuando ya no es necesaria. Al comienzo del programa, en [1.4], solicitamos la memoria y en [1.7] la liberamos justo antes de que el programa termine.

Build and run (Compilar y ejecutar)

Ejecutemos el programa que ha preparado Apple [1]. En primer lugar necesitamos abrir la ventana Console (Consola), que está en el menú Run, para ver los resultados. Después pulsaremos el icono del martillo con el texto "Build and Run" para que se compile y ejecute el programa.
04 Build
El botón Build and Run.
El programa se ejecuta y se muestran sus resultados en la ventana Console, junto con información adicional. La última línea notifica que el programa ha finalizado con un valor de estado 0. Ese es el valor que ha devuelto la función main(), tal como vimos en el capítulo 3 [7.9]. Por tanto, nuestro programa ha llegado hasta la última línea sin haber terminado prematuramente. ¡No está mal para empezar!

Control de errores

Vayamos al ejemplo [1] y veamos qué sucede cuando hay un error en el programa. Por ejemplo, he reemplazado la sentencia NSLog() con otra, pero he olvidado poner el carácter punto y coma al final.
//[2]
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  // insert code here...
  NSLog(@"Julia es mi actriz favorita")   //¡Oh, he olvidado el punto y coma!
  [pool drain];  //[2.9]
  return 0;
}
Para compilar la aplicación pulsa el icono Build en la barra de herramientas (si no lo tienes, pulsa la opción Build dentro del menú Build). Aparecerá un indicador rojo antes de la línea [2.9].
05 Parse Error
Xcode señala un error de compilación.
Según la versión de Xcode podrás ver una descripción del error a la derecha de la línea o tendrás que pulsar en el marcador rojo para que se despliegue la descripción del error.
Lo primero que hace el compilador es analizar el código, recorriendo cada línea para comprobar si puede entender su contenido. Nosotros, para ayudarle, tenemos que dejarle algunas pistas. Por ejemplo, antes de cada sentencia import hay que poner una almohadilla (#). También, para indicar el final de una instrucción, hay que poner un punto y coma. En el momento en que llega a la línea [2.9] es cuando el compilador se da cuenta de que algo va mal, pero no sabe que el problema no está en esta línea sino en la anterior, en la que falta el punto y coma. La lección que debemos aprender es que la información que nos da el compilador no siempre es una descripción precisa del error, e incluso puede que no sea exacta la posición del error (aunque seguro que está muy cerca).
Arregla el programa añadiendo el punto y coma y ejecútalo de nuevo para asegurarte de que funciona.

Nuestra primera aplicación

Ahora vamos a coger el programa que preparamos en el capítulo anterior y lo mezclamos con el código que ha escrito ya Apple. Debería quedar algo así [3]:
//[3]
#import <Foundation/Foundation.h>
float calculaAreaDelCirculo(float radio); //[3.3]
float calculaAreaDelRectangulo(float ancho, float alto); //[3.4]
int main(int argc, const char * argv[])    // [3.6]
{
 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    float anchoDelDibujo, altoDelDibujo, areaDelDibujo,
        radioDelCirculo, areaDelCirculo;
    anchoDelDibujo  = 8.0;
    altoDelDibujo = 4.5;
    radioDelCirculo  = 5.0;
    areaDelDibujo = calculaAreaDelRectangulo(anchoDelDibujo, altoDelDibujo);
    areaDelCirculo = calculaAreaDelCirculo(radioDelCirculo);
    NSLog(@"Area del círculo: %10.2f.", areaDelCirculo);
    NSLog(@"Area del cuadrado: %f.", areaDelDibujo);
 [pool drain];
    return 0;
}
float calculaAreaDelCirculo(float radio)  // [3.22]
{
    float area;
    area = 3.1416 * radio * radio;
    return area;
}
float calculaAreaDelRectangulo(float ancho, float alto) // [3.29]
{
    return ancho * alto;
}
Toma tu tiempo para asegurarte de que entiendes la estructura del programa. Tenemos las declaraciones de nuestras propias funciones en [3.3 y 3.4] antes de la función main() en la línea [3.6]. Nuestras funciones están implementadas fuera de las llaves de la función main() y hemos puesto el cuerpo de nuestra función main() en el lugar que nos había indicado Apple.
Cuando ejecutemos el programa, obtendremos la siguiente salida:
Running…
2010-03-14 00:54:24.494 justatry[8613:a0f] Area del círculo:      78.54.
2010-03-14 00:54:24.496 justatry[8613:a0f] Area del cuadrado: 36.000000.
Debugger stopped.
Program exited with status value:0.

Depurando

Según se van complicando los programas, se hacen más difíciles de depurar. Xcode nos da la opción de saber qué sucede dentro del programa mientras está corriendo. Para ello haremos click con el ratón en el margen gris que está a la izquierda del código (en la zona en la que aparecen los números de línea), en la línea en la que queremos que el programa nos muestre los valores de las variables. En ese punto Xcode insertará un "breakpoint" (punto de ruptura), representado por una flecha azul.
06 Breakpoint
Colocando breakpoints (puntos de ruptura) en nuestro código. En este caso podemos ver uno en la línea 15
En la siguiente sección veremos cómo el Debugger nos muestra el estado de las variables al llegar al punto de ruptura. Pero ten en cuenta que serán los valores de "antes" de que se ejecute la línea en la que hemos parado, así que puede que te convenga poner el breakpoint "después" de la línea que te interesa.
En cuanto insertes el primer breakpoint verás que el icono con el martillo cambia ligeramente y en el texto se lee "Build and Debug" (Compilar y depurar). En versiones anteriores tienes que mantener pulsado el ratón en el icono del martillo hasta que aparezca un menú.
07 Build Menu
El botón de compilar y depurar.
Para seguir lo que está sucediendo necesitas abrir dos ventanas: Console y Debugger, que están en el menú Run. La Consola mostrará un texto parecido a este:
[Session started at 2009-06-03 15:48:02 +1000.]
Loading program into debugger…
GNU gdb 6.3.50-20050815 (Apple version gdb-956) (Wed Apr 30 05:08:47 UTC 2008)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".tty /dev/ttys000
Program loaded.
sharedlibrary apply-load-rules all
run
[Switching to process 86746 local thread 0x2d03]
Running…
 
Esto quiere indica que nuestra aplicación ha sido compilada y lanzada, y que se ha cargado el Debugger (depurador).
La ventana del Debugger tendrá un aspecto parecido a este:
08 Debugger
El Depurador de Xcode te permite ejecutar el programa paso a paso y consultar el valor de las variables.
El programa se ejecutará hasta que alcance el primer breakpoint. Si compruebas el panel superior derecho puedes leer el valor de las variables. Se muestran en color rojo los valores que han cambiado desde el anterior breakpoint. Para continuar la ejecución pulsa el botón Continue. Los botones Step Over y Step Into sirven para ejecutar el programa instrucción a instrucción. Prueba el Debugger durante un rato para familiarizarte con él, es una herramienta poderosa.

Conclusión

Ya tenemos todo lo necesario para escribir, depurar y ejecutar programas sencillos para Mac OS X.
Si no deseas realizar programas con interfaz gráfico, todo lo que te falta es ir conociendo en profundidad Objective-C para desarrollar programas no gráficos más sofisticados. En los siguientes capítulos vamos a hacer exactamente eso. Y después, nos sumergiremos en aplicaciones con GUI (Interfaz Gráfico de Usuario). ¡Sigue leyendo!





Fuente: cocoalab.com / luisiglesias