Reduced line lengths larger than 80 characters

This commit is contained in:
David Hsieh 2015-10-19 14:54:53 -07:00
parent 6c0652bc9c
commit 6616ee7156

View File

@ -38,7 +38,8 @@ int main (int argc, const char * argv[])
{ {
// Crear un autorelease pool para manejar la memoria al programa // Crear un autorelease pool para manejar la memoria al programa
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Si se utiliza el conteo automático de referencias (ARC), utiliza @autoreleasepool: // Si se utiliza el conteo automático de referencias (ARC),
// utiliza @autoreleasepool:
@autoreleasepool { @autoreleasepool {
// Utiliza NSLog para imprimir líneas a la consola // Utiliza NSLog para imprimir líneas a la consola
@ -53,13 +54,14 @@ int main (int argc, const char * argv[])
long myPrimitive2 = 234554664565; long myPrimitive2 = 234554664565;
// Declaraciones de objetos // Declaraciones de objetos
// Pon el * como prefijo de los nombre de las variables para declaraciones de // Pon el * como prefijo de los nombre de las variables para declaraciones
// objetos de tipos fuertes // de objetos de tipos fuertes
MyClass *myObject1 = nil; // Tipo fuerte MyClass *myObject1 = nil; // Tipo fuerte
id myObject2 = nil; // Tipo débil id myObject2 = nil; // Tipo débil
// %@ es un objeto // %@ es un objeto
// 'description' es una convención para mostrar el valor de los objetos // 'description' es una convención para mostrar el valor de los objetos
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // imprime => "(null) y (null)" NSLog(@"%@ and %@", myObject1, [myObject2 description]);
// imprime => "(null) and (null)"
// String // String
NSString *worldString = @"World"; NSString *worldString = @"World";
@ -216,7 +218,8 @@ int main (int argc, const char * argv[])
int ii = 0; int ii = 0;
while (ii < 4) while (ii < 4)
{ {
NSLog(@"%d,", ii++); // ii++ incrementa ii en la misma línea, luego de utilizar su valor NSLog(@"%d,", ii++); // ii++ incrementa ii en la misma línea, luego de
// utilizar su valor
} // imprime => "0," } // imprime => "0,"
// "1," // "1,"
// "2," // "2,"
@ -242,7 +245,8 @@ int main (int argc, const char * argv[])
// "2," // "2,"
// "3," // "3,"
// Objeto de ciclos For. Puede ser utilizado con cualquier tipo de objecto de Objective-C // Objeto de ciclos For. Puede ser utilizado con cualquier tipo de objecto de
// Objective-C
for (id item in values) { for (id item in values) {
NSLog(@"%@,", item); NSLog(@"%@,", item);
} // imprime => "0," } // imprime => "0,"
@ -256,7 +260,8 @@ int main (int argc, const char * argv[])
// Tus declaraciones aquí // Tus declaraciones aquí
@throw [NSException exceptionWithName:@"FileNotFoundException" @throw [NSException exceptionWithName:@"FileNotFoundException"
reason:@"File Not Found on System" userInfo:nil]; reason:@"File Not Found on System" userInfo:nil];
} @catch (NSException * e) // utiliza: @catch (id exceptionName) para atrapar todos los objetos } @catch (NSException * e) // utiliza: @catch (id exceptionName) para atrapar
// todos los objetos
{ {
NSLog(@"Exception: %@", e); NSLog(@"Exception: %@", e);
} @finally } @finally
@ -265,7 +270,8 @@ int main (int argc, const char * argv[])
} // imprime => "Exception: File Not Found on System" } // imprime => "Exception: File Not Found on System"
// "Finally. Time to clean up." // "Finally. Time to clean up."
// Los objetos NSError son útiles para argumentos de función para los errores de usuario. // Los objetos NSError son útiles para argumentos de función para los
// errores de usuario.
NSError *error = [NSError errorWithDomain:@"Invalid email." code:4 userInfo:nil]; NSError *error = [NSError errorWithDomain:@"Invalid email." code:4 userInfo:nil];
/////////////////////////////////////// ///////////////////////////////////////
@ -305,20 +311,27 @@ int main (int argc, const char * argv[])
// @property tipo nombre; <= declaración de propiedades // @property tipo nombre; <= declaración de propiedades
// -/+ (tipo) Declaración de método; <= Declaración de método // -/+ (tipo) Declaración de método; <= Declaración de método
// @end // @end
@interface MyClass : NSObject <MyProtocol> // NSObject es la clase de objeto base de Objective-C. @interface MyClass : NSObject <MyProtocol> // NSObject es la clase de objeto
// base de Objective-C.
{ {
// Declaraciones de variables de instancia (puede existir en el archivo de interfaz o de implementación) // Declaraciones de variables de instancia (puede existir en el archivo de
// interfaz o de implementación)
int count; // Acceso protegido por defecto. int count; // Acceso protegido por defecto.
@private id data; // Acceso privado (Más conveniente de declarar en el archivo de implementación) @private id data; // Acceso privado (Más conveniente de declarar en el
// archivo de implementación)
NSString *name; NSString *name;
} }
// Notación conveneinte para acceso público de las variables para generar un método setter // Notación conveneinte para acceso público de las variables para generar un
// Por defecto, el nombre del método setter 'set' seguido del nombre de variable @property // método setter
// Por defecto, el nombre del método setter 'set' seguido del nombre de
// variable @property
@property int propInt; // Nombre del método 'setter' = 'setPropInt' @property int propInt; // Nombre del método 'setter' = 'setPropInt'
@property (copy) id copyId; // (copy) => Copia el objeto durante la asignación @property (copy) id copyId; // (copy) => Copia el objeto durante la asignación
// (readonly) => No se le puede asignar un valor fuera de @interface // (readonly) => No se le puede asignar un valor fuera de @interface
@property (readonly) NSString *roString; // utiliza @synthesize en @implementation para crear un accesor @property (readonly) NSString *roString; // utiliza @synthesize en
// Puedes personalizar el nombre del getter y del setter en lugar de utilizar el nombre por defecto "set". // @implementation para crear un accesor
// Puedes personalizar el nombre del getter y del setter en lugar de utilizar
// el nombre por defecto "set".
@property (getter=lengthGet, setter=lengthSet:) int length; @property (getter=lengthGet, setter=lengthSet:) int length;
// Métodos // Métodos
@ -334,23 +347,23 @@ int main (int argc, const char * argv[])
// Métodos de constructor con argumentos // Métodos de constructor con argumentos
- (id)initWithDistance:(int)defaultDistance; - (id)initWithDistance:(int)defaultDistance;
// Los nombres de los métodos de Objective-C son muy descriptivos. Siempre nombra los métodos // Los nombres de los métodos de Objective-C son muy descriptivos.
// de acuerdo con sus argumentos // Siempre nombra los métodos de acuerdo con sus argumentos
@end // Define el final de la interfaz @end // Define el final de la interfaz
// Para acceder a las variables públicas desde el archivo de implementación, @property genera // Para acceder a las variables públicas desde el archivo de implementación,
// un método setter automáticamente. El nombre del método es 'set' seguido de un nombre de variable // @property genera un método setter automáticamente. El nombre del método
// @property: // es 'set' seguido de un nombre de variable @property:
MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia del objeto MyClass MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia del objeto MyClass
[myClass setCount:10]; [myClass setCount:10];
NSLog(@"%d", [myClass count]); // imprime => 10 NSLog(@"%d", [myClass count]); // imprime => 10
// O utilizando los métodos getter y setter personalizados en @interface: // O utilizando los métodos getter y setter personalizados en @interface:
[myClass lengthSet:32]; [myClass lengthSet:32];
NSLog(@"%i", [myClass lengthGet]); // imprime => 32 NSLog(@"%i", [myClass lengthGet]); // imprime => 32
// Por conveniencia, puedes utilizar la notación de punto para asignar y acceder a las variables // Por conveniencia, puedes utilizar la notación de punto para asignar y
// de una instancia de objeto. // acceder a las variables de una instancia de objeto.
myClass.count = 45; myClass.count = 45;
NSLog(@"%i", myClass.count); // imprime => 45 NSLog(@"%i", myClass.count); // imprime => 45
@ -363,13 +376,14 @@ MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia de objeto Mycla
NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Hello"]; NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Hello"];
// Selectors // Selectors
// Una forma dinámica de representar métodos. Utilizados para llamar métodos de una clase, // Una forma dinámica de representar métodos. Utilizados para llamar métodos
// pasar métodos a través de funciones para avisar a otras clases para que lo llamen, y // de una clase, pasar métodos a través de funciones para avisar a otras clases
// para guardar métodos como una variable. // para que lo llamen, y para guardar métodos como una variable.
// SEL es el tipo de dato. @selector() devuelve un selector del nombre de método proveído // SEL es el tipo de dato. @selector() devuelve un selector del nombre de
// methodAparameterAsString:andAParameterAsNumber: es un nombre para un método en MyClass // método proveído methodAparameterAsString:andAParameterAsNumber: es un nombre
// para un método en MyClass
SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:); SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
if ([myClass respondsToSelector:selectorVar]) { // Revisa si la clase contiene un método if ([myClass respondsToSelector:selectorVar]) { // Revisa si la clase contiene el método
// Debe de poner todos los argumentos de método en un solo objeto para mandar una // Debe de poner todos los argumentos de método en un solo objeto para mandar una
// función performSelector. // función performSelector.
NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil]; NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil];
@ -390,8 +404,8 @@ if ([myClass respondsToSelector:selectorVar]) { // Revisa si la clase contiene u
_count = 5; // Hace referencia a "int count" de la interfaz de MyClass _count = 5; // Hace referencia a "int count" de la interfaz de MyClass
// Accede variables definidas en el archivo de implementación: // Accede variables definidas en el archivo de implementación:
distance = 18; // Hace referencia a "long distance" de la implementación de MyClass distance = 18; // Hace referencia a "long distance" de la implementación de MyClass
// Para utilizar una variable @property en el archivo de implementación, utiliza @synthesize // Para utilizar una variable @property en el archivo de implementación, utiliza
// para crear una variable de acceso: // @synthesize para crear una variable de acceso:
@synthesize roString = _roString; // _roString ahora está disponible en @implementation @synthesize roString = _roString; // _roString ahora está disponible en @implementation
// Lamado antes de llamar algún método o instanciar cualquier objeto // Lamado antes de llamar algún método o instanciar cualquier objeto
@ -406,7 +420,8 @@ distance = 18; // Hace referencia a "long distance" de la implementación de MyC
// del objeto es cero // del objeto es cero
- (void)dealloc - (void)dealloc
{ {
[height release]; // Si no utilizas ARC, asegúrate de liberar las variables de objeto de las clases [height release]; // Si no utilizas ARC, asegúrate de liberar las variables de
// objeto de las clases
[super dealloc]; // y llama el método dealloc de la clase padre [super dealloc]; // y llama el método dealloc de la clase padre
} }
@ -414,7 +429,8 @@ distance = 18; // Hace referencia a "long distance" de la implementación de MyC
// Este es el constructor por defecto que es llamado cuando el objeto es inicializado. // Este es el constructor por defecto que es llamado cuando el objeto es inicializado.
- (id)init - (id)init
{ {
if ((self = [super init])) // 'super' es utilizado para acceder a los métodos de la clase padre. if ((self = [super init])) // 'super' es utilizado para acceder a los
// métodos de la clase padre.
{ {
self.count = 1; // 'self' es utilizado para que el objeto se llame a sí mismo. self.count = 1; // 'self' es utilizado para que el objeto se llame a sí mismo.
} }
@ -466,18 +482,20 @@ distance = 18; // Hace referencia a "long distance" de la implementación de MyC
/////////////////////////////////////// ///////////////////////////////////////
// Categorías // Categorías
/////////////////////////////////////// ///////////////////////////////////////
// Una categoría es un grupo de métodos diseñados para extender una clase. Te permiten agregar // Una categoría es un grupo de métodos diseñados para extender una clase.
// nuevos métodos a una clase existente por propósitos de organización. Éstos no deben de ser // Te permiten agregar nuevos métodos a una clase existente por propósitos
// confundidos con subclases. // de organización. Éstos no deben de serconfundidos con subclases.
// Las subclases existen para CAMBIAR la funcionalidad de un objeto mientras que las categorías // Las subclases existen para CAMBIAR la funcionalidad de un objeto mientras
// le AGREGAN funcionalidad de un objeto. // que las categoríasle AGREGAN funcionalidad de un objeto.
// Las categorías te permiten: // Las categorías te permiten:
// -- Agregar métodos a una clase existente por propósitos de oganización. // -- Agregar métodos a una clase existente por propósitos de oganización.
// -- Extender clases de objetos de Objective-C (ejemplo: NSString) para agregar tus propios métodos. // -- Extender clases de objetos de Objective-C (ejemplo: NSString) para
// agregar tus propios métodos.
// -- Agregar la habilidad de crear métodos protegidos y privados para las clases. // -- Agregar la habilidad de crear métodos protegidos y privados para las clases.
// NOTA: No sobreescribas los métodos de las clases base en una categoría aunque tengas la habilidad // NOTA: No sobreescribas los métodos de las clases base en una categoría
// de poder hacerlo. Sobreescribir métodos puede causar errores en la compilación después entre // aunque tengas la habilidad de poder hacerlo. Sobreescribir métodos puede
// diferentes categorías y puede arruinar el propósito de las categorías de solo AGREGAR funcionalidad. // causar errores en la compilación después entre diferentes categorías y
// puede arruinar el propósito de las categorías de solo AGREGAR funcionalidad.
// Utiliza subclass para sobreescribir métodos. // Utiliza subclass para sobreescribir métodos.
// Aquí una clase base simple, Car. // Aquí una clase base simple, Car.
@ -508,17 +526,20 @@ distance = 18; // Hace referencia a "long distance" de la implementación de MyC
@end @end
// Ahora, si quisieramos crear un objeto Truck (Camión), crearíamos una subclase de Car (Carro) como // Ahora, si quisieramos crear un objeto Truck (Camión), crearíamos una
// si le cambiaramos de funcionalidad de Car para que se comporte como un camión. Pero digamos que // subclase de Car (Carro) como si le cambiaramos de funcionalidad de Car
// únicamente queremos agregar funcionalidad al Car (Carro) existente. Un buen ejemplo sería limpiar // para que se comporte como un camión. Pero digamos que únicamente queremos
// el carro. Así que crearíamos una cateog®iea para agregar los métodos de limpieza: // agregar funcionalidad al Car (Carro) existente. Un buen ejemplo sería
// limpiar el carro. Así que crearíamos una cateog®iea para agregar los
// métodos de limpieza:
// Archivo @interface: Car+Clean.h (NombreBaseDeClase+NombreDeCategoria.h) // Archivo @interface: Car+Clean.h (NombreBaseDeClase+NombreDeCategoria.h)
#import "Car.h" // Asegúrate de improtar la clase que deseas extener. #import "Car.h" // Asegúrate de improtar la clase que deseas extener.
@interface Car (Clean) // El nombre de la categoría está dentro de (), seguido del nombre de la @interface Car (Clean) // El nombre de la categoría está dentro de (),
// clase base // seguido del nombre de la clase base
- (void)washWindows; // Nombres de los nuevos métodos que le agregamos a nuestro objeto Car - (void)washWindows; // Nombres de los nuevos métodos que le agregamos
// a nuestro objeto Car
- (void)wax; - (void)wax;
@end @end
@ -537,10 +558,12 @@ distance = 18; // Hace referencia a "long distance" de la implementación de MyC
@end @end
// Cualquier instancia del objeto Car tiene la habilidad de utilizar una categoría. Todo lo // Cualquier instancia del objeto Car tiene la habilidad de utilizar una
// que necesitan es importarlo: // categoría. Todo lo que necesitan es importarlo:
#import "Car+Clean.h" // Importa todas las diferentes categorías que necesites utilizar #import "Car+Clean.h" // Importa todas las diferentes categorías que
#import "Car.h" // También debes de importar la clase base para su funcionalidad original // necesites utilizar
#import "Car.h" // También debes de importar la clase base para su
// funcionalidad original
int main (int argc, const char * argv[]) { int main (int argc, const char * argv[]) {
@autoreleasepool { @autoreleasepool {
@ -554,23 +577,27 @@ int main (int argc, const char * argv[]) {
return 0; return 0;
} }
// Objective-C no tiene declaraciones para métodos protegidos, pero los puedes simular. // Objective-C no tiene declaraciones para métodos protegidos, pero los puedes
// Crea una categoría conteniendo todos los métodos protegidos, luego importa ÚNICAMENTE // simular. Crea una categoría conteniendo todos los métodos protegidos,
// al archivo @implementation de una clase que pertenece a la clase Car. // luego importa ÚNICAMENTE al archivo @implementation de una clase que
@interface Car (Protected) // Nombrando la categoría 'Protected' para recordar que los métodos // pertenece a la clase Car.
// están protegidos @interface Car (Protected) // Nombrando la categoría 'Protected' para
// recordar que los métodos están protegidos
- (void)lockCar; // Los métodos enlistados aquí solo puedens ser creados por objetos Car - (void)lockCar; // Los métodos enlistados aquí solo puedens ser creados
// por objetos Car
@end @end
// Para utilizar los métodos protegidos, importa la categoría, luego implementa sus métodos: // Para utilizar los métodos protegidos, importa la categoría,
#import "Car+Protected.h" // Recuerda, importa únicamente el archivo de @implementation // luego implementa sus métodos:
#import "Car+Protected.h" // Recuerda, importa únicamente el archivo
// de @implementation
@implementation Car @implementation Car
- (void)lockCar { - (void)lockCar {
NSLog(@"Car locked."); // Las instancias de Car no puede utilizar lockCar porque no se NSLog(@"Car locked."); // Las instancias de Car no puede utilizar
// encuentra en @interface // lockCar porque no se encuentra en @interface
} }
@end @end
@ -578,8 +605,8 @@ int main (int argc, const char * argv[]) {
/////////////////////////////////////// ///////////////////////////////////////
// Extensiones // Extensiones
/////////////////////////////////////// ///////////////////////////////////////
// Las Extensions te permiten sobreescribir atributos de propiedades de acceso público y métodos de // Las Extensions te permiten sobreescribir atributos de propiedades de
// un @interface // acceso público y métodos de un @interface
// Archivo @interface: Shape.h // Archivo @interface: Shape.h
@interface Shape : NSObject @interface Shape : NSObject
@ -588,17 +615,21 @@ int main (int argc, const char * argv[]) {
- (int)getNumOfSides; - (int)getNumOfSides;
@end @end
// Puedes sobreescribir la variable numOfSides o el métodos getNumOfSlides para modificarlos con una // Puedes sobreescribir la variable numOfSides o el métodos getNumOfSlides
// extensión: // para modificarlos con una extensión:
// Archivo @implementation: Shape.m // Archivo @implementation: Shape.m
#import "Shape.h" #import "Shape.h"
// Las extensiones se encuentran en el mismo archivo que el archivo de @implementation // Las extensiones se encuentran en el mismo archivo que el archivo
@interface Shape () // () después del nombre de la clase base declara una extensión // de @implementation
@interface Shape () // () después del nombre de la clase base declara
// una extensión
@property (copy) NSNumber *numOfSides; // Hacer numOfSlides copy en lugar de readonly. @property (copy) NSNumber *numOfSides; // Hacer numOfSlides copy en lugar
-(NSNumber)getNumOfSides; // Hacer que getNumOfSides devuelva un NSNumber en lugar de un int. // de readonly.
-(void)privateMethod; // También puedes crear una nuevos métodos privados dentro de las -(NSNumber)getNumOfSides; // Hacer que getNumOfSides devuelva un NSNumber
// extensiones // en lugar de un int.
-(void)privateMethod; // También puedes crear una nuevos métodos privados
// dentro de las extensiones
@end @end
// @implementation principal: // @implementation principal:
@ -606,8 +637,8 @@ int main (int argc, const char * argv[]) {
@synthesize numOfSides = _numOfSides; @synthesize numOfSides = _numOfSides;
-(NSNumber)getNumOfSides { // Todas las declaraciones dentro de extensions deben de ser -(NSNumber)getNumOfSides { // Todas las declaraciones dentro de extensions
// dentro de @implementation // deben de ser dentro de @implementation
return _numOfSides; return _numOfSides;
} }
-(void)privateMethod { -(void)privateMethod {
@ -619,36 +650,44 @@ int main (int argc, const char * argv[]) {
/////////////////////////////////////// ///////////////////////////////////////
// Protocolos // Protocolos
/////////////////////////////////////// ///////////////////////////////////////
// Un protocolo declara métodos que pueden ser implementados por cualquier otra clase // Un protocolo declara métodos que pueden ser implementados por cualquier otra
// Los protocolos no son clases. Simplementen define una interfaz que otros objetos // clase. Los protocolos no son clases. Simplementen define una interfaz que
// deben de implementar. // otros objetos deben de implementar.
// Archivo @protocol: "CarUtilities.h" // Archivo @protocol: "CarUtilities.h"
@protocol CarUtilities <NSObject> // <NSObject> => Nombre de otro protocolo que se incluye en éste @protocol CarUtilities <NSObject> // <NSObject> => Nombre de otro protocolo
@property BOOL engineOn; // La clase que lo adopta debe de utilizar @synthesize para todas las // que se incluye en éste
// @properties definidas @property BOOL engineOn; // La clase que lo adopta debe de utilizar
// @synthesize para todas las @properties definidas
- (void)turnOnEngine; // y todos los métodos definidos - (void)turnOnEngine; // y todos los métodos definidos
@end @end
// A continuación una clase ejemplo que implementa el protcolo // A continuación una clase ejemplo que implementa el protcolo
#import "CarUtilities.h" // Importar el archivo @protocol. #import "CarUtilities.h" // Importar el archivo @protocol.
@interface Car : NSObject <CarUtilities> // El nombre del protocolo dentro de <> @interface Car : NSObject <CarUtilities> // El nombre del protocolo dentro de <>
// No necesitas los nombres de @property o métodos aquí para CarUtilities. Estos solo // No necesitas los nombres de @property o métodos aquí para CarUtilities.
// es requerido por @implementation. // Estos solo es requerido por @implementation.
- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // También Puedes utilizar protocolos como datos. - (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // También Puedes
// utilizar protocolos
// como datos.
@end @end
// El @implementation necesita que se implementen @properties y métodos del protocolo. // El @implementation necesita que se implementen @properties y métodos
// del protocolo.
@implementation Car : NSObject <CarUtilities> @implementation Car : NSObject <CarUtilities>
@synthesize engineOn = _engineOn; // Crear una declaración @synthesize para el @property engineOn. @synthesize engineOn = _engineOn; // Crear una declaración @synthesize para el
// @property engineOn.
- (void)turnOnEngine { // Implementa turnOnEngine como quieras. Los protocolos no definen - (void)turnOnEngine { // Implementa turnOnEngine como quieras. Los
_engineOn = YES; // cómo implementas un método, con tal de que lo implementes. // protocolos no definen
_engineOn = YES; // cómo implementas un método, con tal de que lo implementes.
} }
// Puedes utilizar un protocolo como data mientras sepas quee métodos y variables tiene implementado. // Puedes utilizar un protocolo como data mientras sepas quee métodos y variables
// tiene implementado.
- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind { - (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
[objectOfSomeKind engineOn]; // Tienes acceso a las variables [objectOfSomeKind engineOn]; // Tienes acceso a las variables
[objectOfSomeKind turnOnEngine]; // y los métodos del objeto [objectOfSomeKind turnOnEngine]; // y los métodos del objeto
[objectOfSomeKind engineOn]; // Puede o no puede ser YES. La clase lo implementa como se quiera. [objectOfSomeKind engineOn]; // Puede o no puede ser YES. La clase lo
// implementa como se quiera.
} }
@end @end
@ -659,18 +698,23 @@ Car *carInstance = [[Car alloc] init];
if ([carInstance engineOn]) { if ([carInstance engineOn]) {
NSLog(@"Car engine is on."); // imprime => "Car engine is on." NSLog(@"Car engine is on."); // imprime => "Car engine is on."
} }
// Asegúrate de revisar si un objeto de tipo 'id' implementa un protocolo antes de llamar a sus métodos: // Asegúrate de revisar si un objeto de tipo 'id' implementa un protocolo antes
// de llamar a sus métodos:
if ([myClass conformsToProtocol:@protocol(CarUtilities)]) { if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol."); NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol.");
} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) { } else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
NSLog(@"This does run as the Car class implements the CarUtilities protocol."); NSLog(@"This does run as the Car class implements the CarUtilities protocol.");
} }
// Las categorías también pueden implementar protcolos: @interface Car (CarCategory) <CarUtilities> // Las categorías también pueden implementar protcolos: @interface Car
// Puedes implementar varios protocolos: @interface Car : NSObject <CarUtilities, CarCleaning> // (CarCategory) <CarUtilities>
// NOTA: Si dos o más protocolos dependen entre sí, asegúrate de declararlos de manera adelantada: // Puedes implementar varios protocolos:
// @interface Car : NSObject <CarUtilities, CarCleaning>
// NOTA: Si dos o más protocolos dependen entre sí, asegúrate de declararlos
// de manera adelantada:
#import "Brother.h" #import "Brother.h"
@protocol Brother; // Declaración adelantada. Sin ésto, el compilador tira un error. @protocol Brother; // Declaración adelantada. Sin ésto, el compilador
// tira un error.
@protocol Sister <NSObject> @protocol Sister <NSObject>
@ -678,10 +722,11 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
@end @end
// Ver si el problema es que Sister depende de Brother, y Broteher dependa de Sister. // Ver si el problema es que Sister depende de Brother,
// y Brother dependa de Sister.
#import "Sister.h" #import "Sister.h"
@protocol Sister; // Estas líenas detienen la recursión, solucionando el problema. @protocol Sister; // Estas líneas detienen la recursión, resolviendo el problema.
@protocol Brother <NSObject> @protocol Brother <NSObject>
@ -693,23 +738,30 @@ if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
/////////////////////////////////////// ///////////////////////////////////////
// Bloques // Bloques
/////////////////////////////////////// ///////////////////////////////////////
// Los bloques son declaraciones de código, tal como una función, pueden ser utilizados como data // Los bloques son declaraciones de código, tal como una función, pueden
// A continuación un bloque simple con un argumento entero que devuelve un el argumento más 4. // ser utilizados como data.
// A continuación un bloque simple con un argumento entero que devuelve
// un el argumento más 4.
int (^addUp)(int n); // Declarar una variable para almacenar el bloque. int (^addUp)(int n); // Declarar una variable para almacenar el bloque.
void (^noParameterBlockVar)(void); // Ejemplo de una declaración de variable de bloque sin argumentos. void (^noParameterBlockVar)(void); // Ejemplo de una declaración de variable
// Los bloques tienen acceso a variables del mismo ámbito. Pero las variables son solo readonly // de bloque sin argumentos.
// y el valor pasado al bloque es el valor de la variable cuando el bloque es creado. // Los bloques tienen acceso a variables del mismo ámbito. Pero las variables
int outsideVar = 17; // Si modificamos outsideVar después de declarar addUp, outsideVar AÚN es 17. // son solo readonly y el valor pasado al bloque es el valor de la variable
__block long mutableVar = 3; // __block hace que las variables se puedan escribir en bloques. // cuando el bloque es creado.
addUp = ^(int n) { // Remueve (int n) para tener un bloque que no recibe ningún parámetro int outsideVar = 17; // Si modificamos outsideVar después de declarar addUp,
// outsideVar AÚN es 17.
__block long mutableVar = 3; // __block hace que las variables se puedan
// escribir en bloques.
addUp = ^(int n) { // Remueve (int n) para tener un bloque que no recibe
// ningún parámetro
NSLog(@"You may have as many lines in a block as you would like."); NSLog(@"You may have as many lines in a block as you would like.");
NSSet *blockSet; // También puedes declarar variables locales. NSSet *blockSet; // También puedes declarar variables locales.
mutableVar = 32; // Asignar un nuevo valor a la variable __block. mutableVar = 32; // Asignar un nuevo valor a la variable __block.
return n + outsideVar; // Declaraciones de retorno son opcionales. return n + outsideVar; // Declaraciones de retorno son opcionales.
} }
int addUp = add(10 + 16); // Llama al bloque de código con argumentos. int addUp = add(10 + 16); // Llama al bloque de código con argumentos.
// Los bloques son usualmente utilizados como argumentos a funciones que son llamados // Los bloques son usualmente utilizados como argumentos a funciones que
// más adelante o para callbacks. // son llamados más adelante o para callbacks.
@implementation BlockExample : NSObject @implementation BlockExample : NSObject
- (void)runBlock:(void (^)(NSString))block { - (void)runBlock:(void (^)(NSString))block {
@ -724,51 +776,72 @@ int addUp = add(10 + 16); // Llama al bloque de código con argumentos.
// Manejo de memoria // Manejo de memoria
/////////////////////////////////////// ///////////////////////////////////////
/* /*
Para cada objeto utilizado en una aplicación, la memoria debe de ser alocada para ese objeto. Cuando Para cada objeto utilizado en una aplicación, la memoria debe de ser alocada
la aplicación termina de utilizar ese objeto, la memoria debe de ser desalocada para asegurar la para ese objeto. Cuando la aplicación termina de utilizar ese objeto, la
eficiencia de la aplicación. memoria debe de ser desalocada para asegurar la eficiencia de la aplicación.
Objetive-C no utiliza garbage collection, y en lugar de eso utiliza conteos de referencias. Mientras Objetive-C no utiliza garbage collection, y en lugar de eso utiliza conteos
haya al menos una referencia del objeto (también conocido como tener un objeto de adueñado), entonces de referencias. Mientras haya al menos una referencia del objeto (también
el objeto estará disponible para su uso. conocido como tener un objeto de adueñado), entonces el objeto estará
disponible para su uso.
Cuando una instancia es dueña un objeto, su contador de referencia incrementa por uno. Cuando Cuando una instancia es dueña un objeto, su contador de referencia incrementa
el objeto es liberado, el contador de referencia decrementa uno. Cuando el conteo de referencia por uno. Cuando el objeto es liberado, el contador de referencia decrementa uno.
es cero, el objeto es removido de la memoria. Cuando el conteo de referencia es cero, el objeto es removido de la memoria.
Con todas las interacciones de los objetos, sigue el patrón de: Con todas las interacciones de los objetos, sigue el patrón de:
(1) Crear e lobjeto, (2) utiliza el objeto, (3) libera el objeto de la memoria. (1) Crear e lobjeto, (2) utiliza el objeto, (3) libera el objeto de la memoria.
*/ */
MyClass *classVar = [MyClass alloc]; // 'alloc' asigna uno al conteo de referencias de classVar. Devuelve un puntero al objeto MyClass *classVar = [MyClass alloc]; // 'alloc' asigna uno al conteo de
// referencias de classVar. Devuelve un
// puntero al objeto
[classVar release]; // Decrementa el conteo de referencias de classVar's [classVar release]; // Decrementa el conteo de referencias de classVar's
// 'retain' // 'retain'
// 'retain' adueña la instancia de objeto existente e incrementa el conteo de referencia por uno. Devuelve un puntero al objeto. // 'retain' adueña la instancia de objeto existente e incrementa el conteo de
MyClass *newVar = [classVar retain]; // Si classVar es liberado, el objeto aún se queda en memoria porque newVar es el dueño. // referencia por uno. Devuelve un puntero al objeto.
[classVar autorelease]; // Remueve el adueñamiento de un objeto al final del bloque @autoreleasepool. Devuelve un puntero al objeto. MyClass *newVar = [classVar retain]; // Si classVar es liberado, el objeto
// aún se queda en memoria porque newVar
// es el dueño.
[classVar autorelease]; // Remueve el adueñamiento de un objeto al final del
// bloque @autoreleasepool. Devuelve un puntero al objeto.
// @property puede utilizar 'retain' y 'assign' también para pequeñas definiciones convenientes // @property puede utilizar 'retain' y 'assign' también para pequeñas
@property (retain) MyClass *instance; // Libera el valor viejo y retiene uno nuevo (referencia fuerte) // definiciones convenientes
@property (assign) NSSet *set; // Apunta a un nuevo valor sin retener/liberar una referencia vieja (débil) @property (retain) MyClass *instance; // Libera el valor viejo y retiene
// uno nuevo (referencia fuerte)
@property (assign) NSSet *set; // Apunta a un nuevo valor sin retener/liberar
// una referencia vieja (débil)
// Conteo Automático de Referencias (ARC) // Conteo Automático de Referencias (ARC)
// Debido a que el manejo de memoria puede ser un dolor, en Xcode 4.2 y iOS 4 se introdujo el Conteo Automático // Debido a que el manejo de memoria puede ser un dolor, en Xcode 4.2 y iOS 4
// de Referencias (ARC). // se introdujo el Conteo Automático de Referencias (ARC).
// ARC es una funcionalidad del compilador que agrega retain, release y autorealase automáticamente, así que al // ARC es una funcionalidad del compilador que agrega retain, release y
// autorealase automáticamente, así que al
// utilizar ARC, no se debe de utilizar retain, release o autorelease. // utilizar ARC, no se debe de utilizar retain, release o autorelease.
MyClass *arcMyClass = [[MyClass alloc] init]; MyClass *arcMyClass = [[MyClass alloc] init];
// ... código utilizando arcMyClass // ... código utilizando arcMyClass
// Sin ARC, necesitarás llamar: [arcMyClass release] luego de terminar de utilizar arcMyClass. Pero con ARC, // Sin ARC, necesitarás llamar: [arcMyClass release] luego de terminar de
// no hay necesidad. Insertará automáticamente la declaración de liberación. // utilizar arcMyClass. Pero con ARC, no hay necesidad. Insertará
// automáticamente la declaración de liberación.
// Mientras que para los atributos de @property 'assign' y 'retain', con ARC utilizarás 'weak' y 'strong' // Mientras que para los atributos de @property 'assign' y 'retain', con ARC
@property (weak) MyClass *weakVar; // 'weak' no adueña el objeto. El conteo de referencias de la instancia original // utilizarás 'weak' y 'strong'
// es fijado a ceor, weakVar autom´åticamente recibe el valor de nil para evitar cualquier 'crashing'. @property (weak) MyClass *weakVar; // 'weak' no adueña el objeto. El conteo de
@property (strong) MyClass *strongVar; // 'strong' se adueña del objeto. Asegura que el objeto se quede en memoria. // referencias de la instancia original
// es fijado a ceor, weakVar automáticamente recibe el valor de nil para
// evitar cualquier 'crashing'.
@property (strong) MyClass *strongVar; // 'strong' se adueña del objeto.
// Asegura que el objeto se quede en memoria.
// Para variables regulares (no variables de @property), utiliza lo siguiente: // Para variables regulares (no variables de @property), utiliza lo siguiente:
__strong NSString *strongString; // Por defecto. La variables de retenida en memoria hasta que se salga del ámbito. __strong NSString *strongString; // Por defecto. La variables de retenida en
__weak NSSet *weakSet; // Referencia débil a un objeto existente. Cuando el objeto existente es liberado, weakSet le es asginado un valor nil // memoria hasta que se salga del ámbito.
__unsafe_unretained NSArray *unsafeArray; // Como __weak, pero unsafeArray no es asginado a nil cuando el objeto existente es liberado. __weak NSSet *weakSet; // Referencia débil a un objeto existente. Cuando el
// objeto existente es liberado, weakSet le es asginado
// un valor nil
__unsafe_unretained NSArray *unsafeArray; // Como __weak, pero unsafeArray no
// es asginado a nil cuando el objeto
// existente es liberado.
``` ```
## Lecturas sugeridas ## Lecturas sugeridas