Category Archives: Programación para iOS
[iOS 03] Consumiendo Servicios Web.
[iOS 02] Programación para iOS, el UIKit Framework y Xcode.
0. Lectura Obligada!
1. Creando un proyecto en XCode: Calculadora RPM
[iOS 01] Introducción a Objective-C y el Foundation Framework.
Curso de Programación Para iOS
Agenda
- Introducción a Objective-C y el Foundation Framework.
- Programación para iOS, el UIKit Framework, Xcode e Interface Builder.
- Consumiendo Servicios Web.
- Aplicaciones Inmersivas.
- ¿?¿
Introducción a Objective-C y el Foundation Framework
1. Historia
Objective-C es un lenguaje de programación orientado a objetos creado como un super-conjunto de C pero que implementase un modelo de objetos parecido al de Smalltalk. Originalmente fue creado por Brad Cox y la corporación StepStone en 1980. En 1988 fue adoptado como lenguaje de programación de NEXTSTEP y en 1992 fue liberado bajo licencia GPL para el compilador GCC. Actualmente se usa como lenguaje principal de programación en Mac OS X y GNUstep.
Tomado de http://es.wikipedia.org/wiki/Objective-C
2. Objective-C es un super conjunto de C
Mejor dicho; todo lo que usted sabe de C sigue funcionando aquí:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | /* Comentarios en bloque con un montón de carreta: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. */ // Comentarios de una sola línea. // Declaraciones del preprocesador como #include, #ifdef, etc. #include <stdio.h> // Las librerías estándar de C. // Declaración de funciones: float multiplique(float a, float b){ // Operadores aritmeticos. return a*b; } // La función main que toma una lista de parámetros de la línea de comandos. int main (int argc, const char * argv[]) { // Tipos de variables primitivos: int a = 2; float pi = 3.141592; char unCaracter = 'z'; // printf y el resto de funciones estándar: printf("Los valores de estas variables:\na:%i pi:%f unCaracter:%c \n", a, pi, unCaracter); // Llamado a funciones. float resultado = multiplique(2.0, 3.0); // Arrays y strings: int losNumerosDelUnoAlDiez[10] = {1,2,3,4,5,6,7,8,9,10}; float unArrayDeTresNumeros[3]; unArrayDeTresNumeros[0] = 1.23; unArrayDeTresNumeros[1] = pi; unArrayDeTresNumeros[2] = -10; char* lasLetrasDeLaAaLaF = "A B C D E F"; // Condicionales: int seraQueSi = 0; if(seraQueSi == 1){ printf("Que si!\n"); } else{ printf("Hmmm... :(\n"); } char unaOpcion = 'c'; switch(unaOpcion){ case 'a': printf("Escogieron la primera opción\n"); break; case 'b': printf("Han escogido la opción del medio\n"); break; case 'c': printf("Bueh, tocó la última\n"); break; default: printf("No escogieron ningúna opción válida\n"); break; } // Bucles: printf("Aquí va el contenido del array losNumerosDelUnoAlDiez:\n"); int len = sizeof(losNumerosDelUnoAlDiez) / sizeof(float); for(int i=0; i<len; i++){ printf("%i ", i); } printf("\n\n"); printf("Cien repeticiones:\n"); int j = 0; while(j < 100){ printf("%i ",j); j++; } printf("\n\n"); // Punteros: float *pUnNumero; float unNumero = 3.0; pUnNumero = &unNumero; printf("La dirección del puntero pUnNumero:%p\n", pUnNumero); printf("El dato que hay almacenado en pUnNumero:%f\n", *pUnNumero); printf("\n"); return 0; } |
3. Otros Tipos Primitivos que no Existen en C:
Bool:
1 2 3 4 5 | Boolean unBool = NO; Boolean otroBool = YES; if(unBool){ printf("Seekas"); } |
Existe ademas un tipo de variable 'id' que permite crear variables para almacenar cuaquier tipo de datos:
1 2 3 4 5 | int unEntero = 2; char unChar = 'B'; id weakTypedVar = unEntero; // Es un entero. weakTypedVar = unChar; // Ahora es un caracter, no hay problema! |
4. Clases y Objetos
Fraccion.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #import <Foundation/Foundation.h> @interface Fraccion : NSObject { int numerador; int denominador; } -(void) setNumerador:(int)n; -(void) setDenominador:(int)d; -(int) numerador; -(int) denominador; -(void)setA:(int)n sobre:(int)d; -(void) print; -(double)convertToNumber; @end |
Fraccion.m:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #import "Fraccion.h" @implementation Fraccion -(void) setNumerador:(int)n{ numerador = n; } -(void) setDenominador:(int)d{ denominador = d; } -(int) numerador{ return numerador; } -(int) denominador{ return denominador; } -(void)setA:(int)n sobre:(int)d{ numerador = n; denominador = d; } -(void) print{ printf("%i/%i\n",numerador,denominador); } -(double)convertToNumber{ if (denominador != 0) { return (double) numerador / denominador; } else{ return 1.0; } } @end |
main.m:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #import <Foundation/Foundation.h> #import "Fraccion.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraccion* unaFraccion = [[Fraccion alloc] init]; [unaFraccion setNumerador:3]; [unaFraccion setDenominador:4]; printf("Una fracción: "); [unaFraccion print]; Fraccion* otraFraccion = [[Fraccion alloc] init]; [otraFraccion setA:1 sobre:2]; double num = [otraFraccion convertToNumber]; printf("Otra fracción convertida a numero:%f\n", num); [pool drain]; return 0; } |
5. Algunas Clases del Foundation Framework
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // La función NSLog es equivalente a printf en programas de línea de comandos pero // en aplicaciones con interfaz gráfica para MacOS o iOS, es capaz de escribir a las // vitacoras del sistema. NSLog(@"Saludos!"); // Strings: // http://developer.apple.com/library/mac/#documentation/cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html NSString* unString = @"Hola"; NSLog(@"%@",unString); int i = 3; NSString* otroString = [NSString stringWithFormat:@"El entero ese de arriba vale %i", i]; NSLog(@"%@",otroString); NSString* otroStringMas = [unString stringByAppendingString:otroString]; NSLog(@"%@",otroStringMas); // NSNumber encapsula los tipos numericos primitivos de C en objetos de // Objective-C con el fin de que puedan interactuar con otros objetos del framework, // por ejemplo, ser agragados a NSArrays. // http://developer.apple.com/library/mac/#documentation/cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html NSNumber* unNumeroEntero = [NSNumber numberWithInt:3]; NSNumber* unNumeroDePuntoFlotante = [NSNumber numberWithFloat:3.141592]; NSNumber* unBooleano = [NSNumber numberWithBool:YES]; NSLog(@"El entero:%i, el flotante:%f y el booleano:%i", [unNumeroEntero intValue], [unNumeroDePuntoFlotante floatValue], [unBooleano boolValue]); // NSArray // http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html NSArray* unArrayConStrings = [NSArray arrayWithObjects:@"Uno", @"Dos", @"Tres", nil]; NSLog(@"%@", unArrayConStrings); NSArray* unArrayMezcladito = [NSArray arrayWithObjects:unNumeroDePuntoFlotante, otroString, nil]; for(id objeto in unArrayMezcladito){ NSLog(@"%@",objeto); } NSMutableArray* mutable = [NSMutableArray array]; [mutable addObject:@"Uno"]; [mutable addObject:[NSNumber numberWithInt:2]]; [mutable addObject:[NSNumber numberWithFloat:3.14159]]; [mutable removeObjectAtIndex:2]; NSLog(@"%@",mutable); // NSDictionary // http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: @"Valor 1", @"Clave 1", [NSNumber numberWithFloat:2.0], @"Clave 2", nil]; id valor = [dict objectForKey:@"Clave 1"]; NSLog(@"El valor: %@",valor); NSMutableDictionary* mutableDict = [NSMutableDictionary dictionary]; [mutableDict setObject:@"Un Valor" forKey:@"clave1"]; [mutableDict setObject:@"Otro Valor" forKey:@"clave1"]; valor = [mutableDict valueForKey:@"clave1"]; NSLog(@"El valor: %@",valor); [pool release]; return 0; } |
6. Categorías
Las categorías son un mecanismo para extender una clase sin utilizar
herencia. Son muy útiles en casos como:
-
Se quiere agregar nuevos métodos a una clase para la cual no se tiene
el código fuente. Por ejemplo, se quiere agregar un método[NSString isEmpty].
Sería poco práctico crear una clase que herede de NSString pues habría que
cambiar todas las instancias de NSString en su programa por
instancias de la nueva clase. -
Se quiere dividir la implementación de una clase muy grande en varios
archivos o varios programadores. -
Se quiere arreglar un bug en la implementación de un método de una
clase para la cual no se tiene el código.
Un Ejemplo:
NSString+IsEmpty.h
1 2 3 4 5 6 7 | #import <Foundation/Foundation.h> @interface NSString (NSString_IsEmpty) -(BOOL)isEmpty; @end |
NSString+IsEmpty.m
1 2 3 4 5 6 7 8 9 10 11 | #import "NSString+IsEmpty.h" @implementation NSString (NSString_IsEmpty) -(BOOL)isEmpty{ NSString* trimmed = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; return [trimmed length]==0; } @end |
main.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #import <Foundation/Foundation.h> #include "NSString+IsEmpty.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSString* unString = @" "; if([unString isEmpty]){ NSLog(@"The string is empty"); } [pool drain]; return 0; } |
7. Protocolos
Los protocolos son un mecanismo para asegurarse de que una clase
implemente ciertos métodos. Son muy útiles para implementar diseños
orientados a objetos desacoplados; en otras palabras, cuando se quiere
usar una clase de tipo id pero se debe asegurar que implemente cierto
método.
Un ejemplo: Muchas especies pueden cantar.
Cantante.h
1 2 3 | @protocol Cantante <NSObject> -(void)cante; @end |
Cerdo.h y Cerdo.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @interface Cerdo : NSObject { } -(void)grunha; @end @implementation Cerdo -(void)grunha{ NSLog(@"GGRRRHHÑFF"); } @end |
Pajaro.h y Pajaro.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @interface Pajaro : NSObject <Cantante> { } -(void)cante; @end @implementation Pajaro -(void)cante{ NSLog(@"Ti tiririri"); } @end |
main.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //Cerdo* unCerdito = [[Cerdo alloc] init]; //[unCerdito cante]; //El compilador emitirá una advertencia (Los cerdos no cantan) y el programa fallará en tiempo de ejecución en esta línea. // Aqui todo bien: Pajaro* unPajarito = [[Pajaro alloc] init]; [unPajarito cante]; // Pero la mejor manera de hacerlo (diseño desacoplado, el programa no depende de la existencia de la clase Pajaro, prodría llegar una Ballena y todo bien.): id<Cantante> unCantanteDeCualquierEspecie; unCantanteDeCualquierEspecie = [[Pajaro alloc] init]; [unCantanteDeCualquierEspecie cante]; [pool drain]; return 0; } |
8. Manejo de Memoria
Todos los objetos tienen una propiedad retainCount. Cuando el
retainCount llega a cero, el objeto es destruido automáticamente y la memoria
es liberada. El conteo es manipulado con los métodos retain y release.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | int main (int argc, const char * argv[]){ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // El retainCount de un objeto despues de creado es 1: NSNumber* unNumero = [[NSNumber alloc] initWithFloat:3.141592]; NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); // Se puede manipular manualmente: [unNumero retain]; NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); [unNumero release]; NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); // Si se llama a release de nuevo, el objeto se destruirá y el programa // fallará en tiempo de ejecución si se le intenta usar de nuevo: // [unNumero release]; // NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); // NSLog(@"El valor de unNumero: %f",[unNumero floatValue]); // Cuando un objeto utiliza a otro, lo debe retener para evitar que se // destruya. Los NSArray, por ejemplo, retienen los objectos que son // agregados al array. NSMutableArray* unArray = [NSMutableArray array]; [unArray addObject:unNumero]; NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); // Ahora, si libero al numero, el array todavía lo estará reteniendo y // no se destruirá: [unNumero release]; NSLog(@"[unNumero retainCount]: %lu",[unNumero retainCount]); NSLog(@"El valor de unNumero: %f",[unNumero floatValue]); [pool drain]; } |
También existen los NSAutoreleasePool y el método [NSObject autorelease]
que sirven para aplazar la destrucción de objetos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | NSAutoreleasePool * aPool = [[NSAutoreleasePool alloc] init]; NSNumber* otroNumero = [[NSNumber alloc] initWithFloat:3.141592653]; // Haga algo con el número... // Destruyalo luego [otroNumero autorelease]; // Fijese que todavía existe: NSLog(@"[otroNumero retainCount]: %lu",[otroNumero retainCount]); NSLog(@"El valor de otroNumero: %f",[otroNumero floatValue]); // Haga muchas mas cosas en su programa... // Ahora si, libere memoria. [aPool release]; // El numero ya no existe, las siguientes líneas matarían al programa. // NSLog(@"[otroNumero retainCount]: %lu",[otroNumero retainCount]); // NSLog(@"El valor de otroNumero: %f",[otroNumero floatValue]); |
El Foundation framework establece una convencion que se deben tener
en cuenta: Todos los métodos que tienen las palabras "init", "alloc" o
"copy" crean un nuevo objeto y usted tiene la responsabilidad de
administrar la memoria para ese objeto (liberar y retener cuando sea
adecuado). Otros métodos que crean objetos como por ejemplo [NSArray que no tienen ninguna de esas palabras, entregan un objeto
array]
"autoreleased" que se liberará automáticamente mas tarde.
Los objetos que usted cree también deben asegurarse de retener otros
objetos cuando los necesiten y liberarlos cuando ya no los necesite. Un ejemplo:
Cantante.h y Cantante.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @interface Cantante : NSObject { NSString* _nombre; } -(void)setNombre:(NSString*)n; -(NSString*)nombre; @end @implementation Cantante -(void)setNombre:(NSString*)n{ _nombre = n; } -(NSString*)nombre{ return _nombre; } @end |
Banda.h y Banda.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | @interface Banda : NSObject { Cantante* _cantante; } -(Cantante*)cantante; -(void)setCantante:(Cantante*)nuevoCantante; -(void)despidaCantante; @end @implementation Banda // Destructor: - (void)dealloc{ NSLog(@"Se acabó la banda..."); [_cantante release]; [super dealloc]; } -(Cantante*)cantante{ return _cantante; } -(void)setCantante:(Cantante*)nuevoCantante{ if(nuevoCantante != _cantante){ [self despidaCantante]; _cantante = nuevoCantante; [_cantante retain]; NSLog(@"%@ quedó contratado.", [_cantante nombre]); } else{ NSLog(@"%@ ya estaba contratado!", [_cantante nombre]); } } -(void)despidaCantante{ if(_cantante != nil){ NSLog(@"%@ quedó despedido.", [_cantante nombre]); [_cantante release]; _cantante = nil; } } @end |
main.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Cantante* juancho = [[Cantante alloc] init]; [juancho setNombre:@"Juancho"]; NSLog(@"Retain count de Juancho antes de ser contratado: %lu", [juancho retainCount]); Banda* losDatsun = [[Banda alloc] init]; [losDatsun setCantante:juancho]; NSLog(@"Retain count de Juancho después de ser contratado: %lu", [juancho retainCount]); Cantante* pedro = [[Cantante alloc] init]; [pedro setNombre:@"Pedro"]; [losDatsun setCantante:pedro]; NSLog(@"Retain count de Juancho:%lu y Pedro:%lu", [juancho retainCount], [pedro retainCount]); [losDatsun release]; NSLog(@"Retain count de Pedro:%lu", [pedro retainCount]); [pool drain]; return 0; } |
Afortunadamente Objective-C proporciona un mecanismo automático que
evita tener que escribir setters y getters manualmente:
9. Setters y Getters Sintetizados (@properties y @synthetize)
Aquí va el ejemplo anterior de nuevo, esta vez utilizando @properties y
@synthetize para generar los getters y setters. Esta es la manera
recomendada de crear sus clases
Cantante:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @interface Cantante : NSObject { NSString* _nombre; } @property(nonatomic,retain) NSString* nombre; @end @implementation Cantante @synthesize nombre=_nombre; @end |
Banda
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | @interface Banda : NSObject { Cantante* _cantante; } @property(nonatomic, retain) Cantante* cantante; -(void)despidaCantante; @end @implementation Banda @synthesize cantante=_cantante; // Destructor: - (void)dealloc{ NSLog(@"Se acabó la banda..."); [_cantante release]; [super dealloc]; } -(void)despidaCantante{ NSLog(@"%@ quedó despedido.", [_cantante nombre]); self.cantante= nil; } @end |
main.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Cantante* juancho = [[Cantante alloc] init]; juancho.nombre = @"Juancho"; NSLog(@"Retain count de Juancho antes de ser contratado: %lu", [juancho retainCount]); Banda* losDatsun = [[Banda alloc] init]; losDatsun.cantante = juancho; NSLog(@"Retain count de Juancho después de ser contratado: %lu", [juancho retainCount]); Cantante* pedro = [[Cantante alloc] init]; [pedro setNombre:@"Pedro"]; losDatsun.cantante = pedro; NSLog(@"Retain count de Juancho:%lu y Pedro:%lu", [juancho retainCount], [pedro retainCount]); [losDatsun release]; NSLog(@"Retain count de Pedro:%lu", [pedro retainCount]); [pool drain]; return 0; } |
10. Mas Recursos
iOs Developer Library: The Objective-C Programming Language
iOs Developer Library: Object Oriented Programming With Objective-C
iOs Developer Library: Foundation Framework Reference
iOs Developer Library: Memory Management Programming Guide
iOs Developer Library: Memory Management Programming Guide for Core Foundation
11. Ejercicio
Suponga que está escribiendo un juego de ciencia ficción con los siguientes requerimientos:
- Existen 3 especies de personajes que los jugadores pueden escoger para
jugar: Wookies, Humanos y Droids. - Existen 2 especies de enemigos que le harán la vida imposible a los
jugadores: Storm Troopers y Siths. - Los jugadores y los enemigos se agrupan en equipos para pelear y
apostar carreras de naves contra los otros. - Cuando un personaje es incluido en un equipo, saluda con el nombre al
resto de sus compañeros. - Cuando un enemigo es incluido en un equipo, mira feo al resto de sus
compañeros. - Los Droids no saben pelear.
- Solo los Wookies y los Sith saben pilotear.
- Cuando un equipo se enfrenta a otro, ganará el que tenga mas
personajes o enemigos en capacidad de pelear. En caso de empate,
ganará uno de los dos aleatoriamente. Pista: la expresiónarc4random() % 74
devuelve un entero aleatorio entre cero y 74. - El equipo que pierda una pelea, escogerá uno de sus integrantes
aleatoriamente y este morirá. - Cuando un equipo apuesta una carrera de naves con otro, ganará quien
tenga menos pasajeros. En caso de empate, ganará aleatoriamente uno de
los dos. Todos los miembros del equipo perdedor mirarán feo a su
piloto.
Haga lo siguiente:
- Escriba las clases Personaje, Enemigo, Equipo, Wookie, Humano, Droid,
StormTrooper y Sith. Con todos los métodos y propiedades que se
necesiten. - Escriba los protocolos <Piloto> y <Soldado> e impleméntelos en las clases adecuadas.
- No se deben presentar situaciones ilógicas como un equipo corriendo
una carrera sin piloto, un personaje saludando al vacío, etc. - Cuando un personaje muere, se debe liberar el espacio que este ocupaba
en memoria.
Se sabrá si se implementaron correctamente las clases si se ejecuta la
siguiente rutina y los mensajes impresos en la consola son los
esperados.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Wookie* chewbacca = [[Wookie alloc] initWithName:@"Chewbacca"]; Humano* hanSolo = [[Humano alloc] initWithName:@"Han Solo"]; Droid* c3PO = [[Droid alloc] initWithName:@"C3PO"]; Equipo* laAlianza = [[Equipo alloc] initWithName:@"La alianza"]; [laAlianza addIntegrante:chewbacca]; [laAlianza addIntegrante:hanSolo]; [laAlianza addIntegrante:c3PO]; [laAlianza assignPiloto:chewbacca]; [laAlianza assignSoldado:chewbacca]; [laAlianza assignSoldado:hanSolo]; StormTrooper* bobaFett = [[StormTrooper alloc] initWithName:@"Boba Fett"]; Sith* vader = [[Sith alloc] initWithName:@"Darth Vader"]; Equipo* elImperio = [[Equipo alloc] initWithName:@"El Imperio"]; [elImperio addIntegrante:bobaFett]; [elImperio addIntegrante:vader]; [elImperio assignPiloto:vader]; [elImperio assignSoldado:vader]; [elImperio assignSoldade:bobaFett]; [elImperio pelearContra:laAlianza]; [elImperio carreraContra:laAlianza]; |
