objc-spanish

This commit is contained in:
David Hsieh 2015-10-19 14:39:09 -07:00
parent f64a678b5c
commit 6c0652bc9c

View File

@ -0,0 +1,780 @@
---
language: Objective-C
contributors:
- ["Eugene Yagrushkin", "www.about.me/yagrushkin"]
- ["Yannick Loriot", "https://github.com/YannickL"]
- ["Levi Bostian", "https://github.com/levibostian"]
translators:
- ["David Hsieh", "http://github.com/deivuh"]
lang: es-es
filename: LearnObjectiveC.m
---
Objective C es el lenguaje de programación principal utilizado por Apple para los sistemas operativos OS X y iOS y sus respectivos frameworks, Cocoa y Cocoa Touch.
Es un lenguaje de programación para propósito general que le agrega al lenguaje de programación C una mensajería estilo "Smalltalk".
```objective_c
// Los comentarios de una sola línea inician con //
/*
Los comentarios de múltiples líneas se ven así.
*/
// Importa los encabezados de Foundation con #import
// Utiliza <> para importar archivos globales (generalmente frameworks)
// Utiliza "" para importar archivos locales (del proyecto)
#import <Foundation/Foundation.h>
#import "MyClass.h"
// Si habilitas módulos para proyectos de iOS >= 7.0 u OS X >= 10.9 en
// Xcode 5, puedes importarlos de la siguiente manera:
@import Foundation;
// El punto de entrada de tu programa es una función llamada
// main con un tipo de retorno entero.
int main (int argc, const char * argv[])
{
// Crear un autorelease pool para manejar la memoria al programa
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Si se utiliza el conteo automático de referencias (ARC), utiliza @autoreleasepool:
@autoreleasepool {
// Utiliza NSLog para imprimir líneas a la consola
NSLog(@"Hello World!"); // Imprimir el string "Hello World!"
///////////////////////////////////////
// Tipos y variables
///////////////////////////////////////
// Declaraciones de primitivos
int myPrimitive1 = 1;
long myPrimitive2 = 234554664565;
// Declaraciones de objetos
// Pon el * como prefijo de los nombre de las variables para declaraciones de
// objetos de tipos fuertes
MyClass *myObject1 = nil; // Tipo fuerte
id myObject2 = nil; // Tipo débil
// %@ es un objeto
// 'description' es una convención para mostrar el valor de los objetos
NSLog(@"%@ and %@", myObject1, [myObject2 description]); // imprime => "(null) y (null)"
// String
NSString *worldString = @"World";
NSLog(@"Hello %@!", worldString); // imprime => "Hello World!"
// NSMutableString es una versión mutable del objeto NSString
NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
[mutableString appendString:@" World!"];
NSLog(@"%@", mutableString); // imprime => "Hello World!"
// Literales de caracteres
NSNumber *theLetterZNumber = @'Z';
char theLetterZ = [theLetterZNumber charValue]; // o 'Z'
NSLog(@"%c", theLetterZ);
// Literales de enteros
NSNumber *fortyTwoNumber = @42;
int fortyTwo = [fortyTwoNumber intValue]; // o 42
NSLog(@"%i", fortyTwo);
NSNumber *fortyTwoUnsignedNumber = @42U;
unsigned int fortyTwoUnsigned = [fortyTwoUnsignedNumber unsignedIntValue]; // o 42
NSLog(@"%u", fortyTwoUnsigned);
NSNumber *fortyTwoShortNumber = [NSNumber numberWithShort:42];
short fortyTwoShort = [fortyTwoShortNumber shortValue]; // o 42
NSLog(@"%hi", fortyTwoShort);
NSNumber *fortyOneShortNumber = [NSNumber numberWithShort:41];
unsigned short fortyOneUnsigned = [fortyOneShortNumber unsignedShortValue]; // o 41
NSLog(@"%u", fortyOneUnsigned);
NSNumber *fortyTwoLongNumber = @42L;
long fortyTwoLong = [fortyTwoLongNumber longValue]; // o 42
NSLog(@"%li", fortyTwoLong);
NSNumber *fiftyThreeLongNumber = @53L;
unsigned long fiftyThreeUnsigned = [fiftyThreeLongNumber unsignedLongValue]; // o 53
NSLog(@"%lu", fiftyThreeUnsigned);
// Literales de punto flotante
NSNumber *piFloatNumber = @3.141592654F;
float piFloat = [piFloatNumber floatValue]; // o 3.141592654f
NSLog(@"%f", piFloat); // imprime => 3.141592654
NSLog(@"%5.2f", piFloat); // imprime => " 3.14"
NSNumber *piDoubleNumber = @3.1415926535;
double piDouble = [piDoubleNumber doubleValue]; // o 3.1415926535
NSLog(@"%f", piDouble);
NSLog(@"%4.2f", piDouble); // imprime => "3.14"
// NSDecimalNumber es una clase de punto-fijo que es más preciso que float o double
NSDecimalNumber *oneDecNum = [NSDecimalNumber decimalNumberWithString:@"10.99"];
NSDecimalNumber *twoDecNum = [NSDecimalNumber decimalNumberWithString:@"5.002"];
// NSDecimalNumber no tiene la capacidad de utilizar los operadores estándares
// +, -, * , /, por lo que cuenta con sus propios operadores:
[oneDecNum decimalNumberByAdding:twoDecNum];
[oneDecNum decimalNumberBySubtracting:twoDecNum];
[oneDecNum decimalNumberByMultiplyingBy:twoDecNum];
[oneDecNum decimalNumberByDividingBy:twoDecNum];
NSLog(@"%@", oneDecNum); // imprime => 10.99 como NSDecimalNumber es inmutable
// Literales BOOL
NSNumber *yesNumber = @YES;
NSNumber *noNumber = @NO;
// o
BOOL yesBool = YES;
BOOL noBool = NO;
NSLog(@"%i", yesBool); // prints => 1
// Objecto arreglo
// Puede contener diferentes tipos de datos, pero deben de ser un objeto de
// Objective-C
NSArray *anArray = @[@1, @2, @3, @4];
NSNumber *thirdNumber = anArray[2];
NSLog(@"Third number = %@", thirdNumber); // imprime => "Third number = 3"
// NSMutableArray es una versión mutable de NSArray, permitiendo el cambio
// de los elementos del arreglo y el agrandado o encojimiento del objeto arreglo.
// Conveniente, pero no tan eficiente como NSArray en cuanto a rendimiento.
NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:2];
[mutableArray addObject:@"Hello"];
[mutableArray addObject:@"World"];
[mutableArray removeObjectAtIndex:0];
NSLog(@"%@", [mutableArray objectAtIndex:0]); // imprime => "World"
// Objecto Diccionario
NSDictionary *aDictionary = @{ @"key1" : @"value1", @"key2" : @"value2" };
NSObject *valueObject = aDictionary[@"A Key"];
NSLog(@"Object = %@", valueObject); // imprime => "Object = (null)"
// NSMutableDictionary también está disponible como un objeto mutable
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
[mutableDictionary setObject:@"value1" forKey:@"key1"];
[mutableDictionary setObject:@"value2" forKey:@"key2"];
[mutableDictionary removeObjectForKey:@"key1"];
// Objeto de Set
NSSet *set = [NSSet setWithObjects:@"Hello", @"Hello", @"World", nil];
NSLog(@"%@", set); // imprime => {(Hello, World)} (el orden puede variar)
// NSMutableSet también está disponible como un objeto mutable
NSMutableSet *mutableSet = [NSMutableSet setWithCapacity:2];
[mutableSet addObject:@"Hello"];
[mutableSet addObject:@"Hello"];
NSLog(@"%@", mutableSet); // prints => {(Hello)}
///////////////////////////////////////
// Operadores
///////////////////////////////////////
// Los operadores funcionan como en el lenguaje C
// Por ejemplo:
2 + 5; // => 7
4.2f + 5.1f; // => 9.3f
3 == 2; // => 0 (NO)
3 != 2; // => 1 (YES)
1 && 1; // => 1 (and lógico)
0 || 1; // => 1 (or lógico)
~0x0F; // => 0xF0 (negación bitwise)
0x0F & 0xF0; // => 0x00 (AND bitwise)
0x01 << 1; // => 0x02 (acarreamiento a la izquierda bitwise (por 1))
///////////////////////////////////////
// Estructuras de control
///////////////////////////////////////
// Declaraciones If-Else
if (NO)
{
NSLog(@"I am never run");
} else if (0)
{
NSLog(@"I am also never run");
} else
{
NSLog(@"I print");
}
// Declaración Switch
switch (2)
{
case 0:
{
NSLog(@"I am never run");
} break;
case 1:
{
NSLog(@"I am also never run");
} break;
default:
{
NSLog(@"I print");
} break;
}
// Declaración de ciclos While
int ii = 0;
while (ii < 4)
{
NSLog(@"%d,", ii++); // ii++ incrementa ii en la misma línea, luego de utilizar su valor
} // imprime => "0,"
// "1,"
// "2,"
// "3,"
// Declaración de ciclos For
int jj;
for (jj=0; jj < 4; jj++)
{
NSLog(@"%d,", jj);
} // imprime => "0,"
// "1,"
// "2,"
// "3,"
// Declaraciones foreach
NSArray *values = @[@0, @1, @2, @3];
for (NSNumber *value in values)
{
NSLog(@"%@,", value);
} // imprime => "0,"
// "1,"
// "2,"
// "3,"
// Objeto de ciclos For. Puede ser utilizado con cualquier tipo de objecto de Objective-C
for (id item in values) {
NSLog(@"%@,", item);
} // imprime => "0,"
// "1,"
// "2,"
// "3,"
// Declaraciones Try-Catch-Finally
@try
{
// Tus declaraciones aquí
@throw [NSException exceptionWithName:@"FileNotFoundException"
reason:@"File Not Found on System" userInfo:nil];
} @catch (NSException * e) // utiliza: @catch (id exceptionName) para atrapar todos los objetos
{
NSLog(@"Exception: %@", e);
} @finally
{
NSLog(@"Finally. Time to clean up.");
} // imprime => "Exception: File Not Found on System"
// "Finally. Time to clean up."
// 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];
///////////////////////////////////////
// Objetos
///////////////////////////////////////
// Crea una instancia de objeto alocando memoria e inicializándola
// Un objeto no es completamente funcional hasta que ambos pasos hayan sido
// completados
MyClass *myObject = [[MyClass alloc] init];
// El modelo de programación orientada a objetos de Objective-C es basada en
// el envío de mensajes a instancias de objetos
// En Objective-C no se llama a un método; se envía un mensaje
[myObject instanceMethodWithParameter:@"Steve Jobs"];
// Limpiar la memoria que se utilizó en el programa
[pool drain];
// Fin de @autoreleasepool
}
// Fin del programa
return 0;
}
///////////////////////////////////////
// Clases y funciones
///////////////////////////////////////
// Declara tu clase en archivo de encabezado (MyClass.h)
// Sintaxis de declaración de clase:
// @interface NombreDeClase : NombreDeClasePadre <ProtocolosImplementados>
// {
// type nombre; <= declaraciones de variables;
// }
// @property tipo nombre; <= declaración de propiedades
// -/+ (tipo) Declaración de método; <= Declaración de método
// @end
@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)
int count; // Acceso protegido por defecto.
@private id data; // Acceso privado (Más conveniente de declarar en el archivo de implementación)
NSString *name;
}
// Notación conveneinte para acceso público de las variables para generar un 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 (copy) id copyId; // (copy) => Copia el objeto durante la asignación
// (readonly) => No se le puede asignar un valor fuera de @interface
@property (readonly) NSString *roString; // utiliza @synthesize en @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;
// Métodos
+/- (return type)methodSignature:(Parameter Type *)parameterName;
// + Para métodos de clase:
+ (NSString *)classMethod;
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight;
// - Para métodos de instancia:
- (NSString *)instanceMethodWithParameter:(NSString *)string;
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number;
// Métodos de constructor con argumentos
- (id)initWithDistance:(int)defaultDistance;
// Los nombres de los métodos de Objective-C son muy descriptivos. Siempre nombra los métodos
// de acuerdo con sus argumentos
@end // Define el final de la interfaz
// Para acceder a las variables públicas desde el archivo de implementación, @property genera
// un método setter automáticamente. El nombre del método es 'set' seguido de un nombre de variable
// @property:
MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia del objeto MyClass
[myClass setCount:10];
NSLog(@"%d", [myClass count]); // imprime => 10
// O utilizando los métodos getter y setter personalizados en @interface:
[myClass lengthSet:32];
NSLog(@"%i", [myClass lengthGet]); // imprime => 32
// Por conveniencia, puedes utilizar la notación de punto para asignar y acceder a las variables
// de una instancia de objeto.
myClass.count = 45;
NSLog(@"%i", myClass.count); // imprime => 45
// Llama a métodos de clase:
NSString *classMethodString = [MyClass classMethod];
MyClass *classFromName = [MyClass myClassFromName:@"Hello"];
// Llama a métodos de instancia:
MyClass *myClass = [[MyClass alloc] init]; // Crea una instancia de objeto Myclass
NSString *stringFromInstanceMethod = [myClass instanceMethodWithParameter:@"Hello"];
// Selectors
// Una forma dinámica de representar métodos. Utilizados para llamar métodos de una clase,
// pasar métodos a través de funciones para avisar a otras clases 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
// methodAparameterAsString:andAParameterAsNumber: es un nombre para un método en MyClass
SEL selectorVar = @selector(methodAParameterAsString:andAParameterAsNumber:);
if ([myClass respondsToSelector:selectorVar]) { // Revisa si la clase contiene un método
// Debe de poner todos los argumentos de método en un solo objeto para mandar una
// función performSelector.
NSArray *arguments = [NSArray arrayWithObjects:@"Hello", @4, nil];
[myClass performSelector:selectorVar withObject:arguments]; // Calls the method
} else {
// NSStringFromSelector() devuelve un NSString del nombre de método de un selector dado
NSLog(@"MyClass does not have method: %@", NSStringFromSelector(selectedVar));
}
// Implementa los métodos de un archivo de implementación (MyClass.m):
@implementation MyClass {
long distance; // Variable de instancia de acceso privado
NSNumber height;
}
// Para acceder a una variable pública del archivo de interfaz, utiliza '_' seguido del
// nombre de la variable:
_count = 5; // Hace referencia a "int count" de la interfaz de MyClass
// Accede variables definidas en el archivo de implementación:
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 crear una variable de acceso:
@synthesize roString = _roString; // _roString ahora está disponible en @implementation
// Lamado antes de llamar algún método o instanciar cualquier objeto
+ (void)initialize
{
if (self == [MyClass class]) {
distance = 0;
}
}
// Contraparte para inicializar un método. Llamado cuando el contador de referencias
// del objeto es cero
- (void)dealloc
{
[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
}
// Los constructores son una manera de crear instancias de una clase
// Este es el constructor por defecto que es llamado cuando el objeto es inicializado.
- (id)init
{
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.
}
return self;
}
// Se pueden crear constructores que contiene argumentos
- (id)initWithDistance:(int)defaultDistance
{
distance = defaultDistance;
return self;
}
+ (NSString *)classMethod
{
return @"Some string";
}
+ (MyClass *)myClassFromHeight:(NSNumber *)defaultHeight
{
height = defaultHeight;
return [[self alloc] init];
}
- (NSString *)instanceMethodWithParameter:(NSString *)string
{
return @"New string";
}
- (NSNumber *)methodAParameterAsString:(NSString*)string andAParameterAsNumber:(NSNumber *)number
{
return @42;
}
// Objective-C no tiene declaraciones de métodos privados, pero pueden ser simulados.
// Para simular un método privado, crea un método en @implementation pero no en @interface.
- (NSNumber *)secretPrivateMethod {
return @72;
}
[self secretPrivateMethod]; // Calls private method
// Métodos declarados dentro de MyProtocol
- (void)myProtocolMethod
{
// statements
}
@end // Declara el final de la implementación
///////////////////////////////////////
// Categorías
///////////////////////////////////////
// Una categoría es un grupo de métodos diseñados para extender una clase. Te permiten agregar
// nuevos métodos a una clase existente por propósitos de organización. Éstos no deben de ser
// confundidos con subclases.
// Las subclases existen para CAMBIAR la funcionalidad de un objeto mientras que las categorías
// le AGREGAN funcionalidad de un objeto.
// Las categorías te permiten:
// -- 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.
// -- 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
// de poder hacerlo. Sobreescribir métodos puede 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.
// Aquí una clase base simple, Car.
@interface Car : NSObject
@property NSString *make;
@property NSString *color;
- (void)turnOn;
- (void)accelerate;
@end
// Y la implementación de la clase simple, Car
#import "Car.h"
@implementation Car
@synthesize make = _make;
@synthesize color = _color;
- (void)turnOn {
NSLog(@"Car is on.");
}
- (void)accelerate {
NSLog(@"Accelerating.");
}
@end
// Ahora, si quisieramos crear un objeto Truck (Camión), crearíamos una subclase de Car (Carro) como
// si le cambiaramos de funcionalidad de Car para que se comporte como un camión. Pero digamos que
// únicamente queremos 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)
#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
// clase base
- (void)washWindows; // Nombres de los nuevos métodos que le agregamos a nuestro objeto Car
- (void)wax;
@end
// Archivo @implementation: Car+Clean.m (NombreBaseDeClase+NombreDeCategoria.m)
#import "Car+Clean.h" // Importa el archivo de @interface de la categoría Clean
@implementation Car (Clean)
- (void)washWindows {
NSLog(@"Windows washed.");
}
- (void)wax {
NSLog(@"Waxed.");
}
@end
// Cualquier instancia del objeto Car tiene la habilidad de utilizar una categoría. Todo lo
// que necesitan es importarlo:
#import "Car+Clean.h" // Importa todas las diferentes categorías que necesites utilizar
#import "Car.h" // También debes de importar la clase base para su funcionalidad original
int main (int argc, const char * argv[]) {
@autoreleasepool {
Car *mustang = [[Car alloc] init];
mustang.color = @"Red";
mustang.make = @"Ford";
[mustang turnOn]; // Utiliza métodos de la clase base Car.
[mustang washWindows]; // Utiliza métodos de la categoría Clean de Car.
}
return 0;
}
// Objective-C no tiene declaraciones para métodos protegidos, pero los puedes simular.
// Crea una categoría conteniendo todos los métodos protegidos, luego importa ÚNICAMENTE
// al archivo @implementation de una clase que pertenece a la clase Car.
@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
@end
// Para utilizar los métodos protegidos, importa la categoría, luego implementa sus métodos:
#import "Car+Protected.h" // Recuerda, importa únicamente el archivo de @implementation
@implementation Car
- (void)lockCar {
NSLog(@"Car locked."); // Las instancias de Car no puede utilizar lockCar porque no se
// encuentra en @interface
}
@end
///////////////////////////////////////
// Extensiones
///////////////////////////////////////
// Las Extensions te permiten sobreescribir atributos de propiedades de acceso público y métodos de
// un @interface
// Archivo @interface: Shape.h
@interface Shape : NSObject
@property (readonly) NSNumber *numOfSides;
- (int)getNumOfSides;
@end
// Puedes sobreescribir la variable numOfSides o el métodos getNumOfSlides para modificarlos con una
// extensión:
// Archivo @implementation: Shape.m
#import "Shape.h"
// Las extensiones se encuentran en el mismo archivo que el archivo 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.
-(NSNumber)getNumOfSides; // Hacer que getNumOfSides devuelva un NSNumber en lugar de un int.
-(void)privateMethod; // También puedes crear una nuevos métodos privados dentro de las
// extensiones
@end
// @implementation principal:
@implementation Shape
@synthesize numOfSides = _numOfSides;
-(NSNumber)getNumOfSides { // Todas las declaraciones dentro de extensions deben de ser
// dentro de @implementation
return _numOfSides;
}
-(void)privateMethod {
NSLog(@"Private method created by extension. Shape instances cannot call me.");
}
@end
///////////////////////////////////////
// Protocolos
///////////////////////////////////////
// Un protocolo declara métodos que pueden ser implementados por cualquier otra clase
// Los protocolos no son clases. Simplementen define una interfaz que otros objetos
// deben de implementar.
// Archivo @protocol: "CarUtilities.h"
@protocol CarUtilities <NSObject> // <NSObject> => Nombre de otro protocolo que se incluye en éste
@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
@end
// A continuación una clase ejemplo que implementa el protcolo
#import "CarUtilities.h" // Importar el archivo @protocol.
@interface Car : NSObject <CarUtilities> // El nombre del protocolo dentro de <>
// No necesitas los nombres de @property o métodos aquí para CarUtilities. Estos solo
// es requerido por @implementation.
- (void)turnOnEngineWithUtilities:(id <CarUtilities>)car; // También Puedes utilizar protocolos como datos.
@end
// El @implementation necesita que se implementen @properties y métodos del protocolo.
@implementation Car : NSObject <CarUtilities>
@synthesize engineOn = _engineOn; // Crear una declaración @synthesize para el @property engineOn.
- (void)turnOnEngine { // Implementa turnOnEngine como quieras. Los 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.
- (void)turnOnEngineWithCarUtilities:(id <CarUtilities>)objectOfSomeKind {
[objectOfSomeKind engineOn]; // Tienes acceso a las variables
[objectOfSomeKind turnOnEngine]; // y los métodos del objeto
[objectOfSomeKind engineOn]; // Puede o no puede ser YES. La clase lo implementa como se quiera.
}
@end
// Las instancias de Car ahora tienen acceso al protocolo.
Car *carInstance = [[Car alloc] init];
[carInstance setEngineOn:NO];
[carInstance turnOnEngine];
if ([carInstance engineOn]) {
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:
if ([myClass conformsToProtocol:@protocol(CarUtilities)]) {
NSLog(@"This does not run as the MyClass class does not implement the CarUtilities protocol.");
} else if ([carInstance conformsToProtocol:@protocol(CarUtilities)]) {
NSLog(@"This does run as the Car class implements the CarUtilities protocol.");
}
// Las categorías también pueden implementar protcolos: @interface Car (CarCategory) <CarUtilities>
// 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"
@protocol Brother; // Declaración adelantada. Sin ésto, el compilador tira un error.
@protocol Sister <NSObject>
- (void)beNiceToBrother:(id <Brother>)brother;
@end
// Ver si el problema es que Sister depende de Brother, y Broteher dependa de Sister.
#import "Sister.h"
@protocol Sister; // Estas líenas detienen la recursión, solucionando el problema.
@protocol Brother <NSObject>
- (void)beNiceToSister:(id <Sister>)sister;
@end
///////////////////////////////////////
// Bloques
///////////////////////////////////////
// Los bloques son declaraciones de código, tal como una función, pueden 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.
void (^noParameterBlockVar)(void); // Ejemplo de una declaración de variable de bloque sin argumentos.
// Los bloques tienen acceso a variables del mismo ámbito. Pero las variables son solo readonly
// y el valor pasado al bloque es el valor de la variable cuando el bloque es creado.
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.");
NSSet *blockSet; // También puedes declarar variables locales.
mutableVar = 32; // Asignar un nuevo valor a la variable __block.
return n + outsideVar; // Declaraciones de retorno son opcionales.
}
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
// más adelante o para callbacks.
@implementation BlockExample : NSObject
- (void)runBlock:(void (^)(NSString))block {
NSLog(@"Block argument returns nothing and takes in a NSString object.");
block(@"Argument given to block to execute."); // Calling block.
}
@end
///////////////////////////////////////
// Manejo de memoria
///////////////////////////////////////
/*
Para cada objeto utilizado en una aplicación, la memoria debe de ser alocada para ese objeto. Cuando
la aplicación termina de utilizar ese objeto, la 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
haya al menos una referencia del objeto (también 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
el objeto es liberado, el contador de referencia decrementa uno. 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:
(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
[classVar release]; // Decrementa el conteo de referencias de classVar's
// 'retain'
// 'retain' adueña la instancia de objeto existente e incrementa el conteo de referencia por uno. 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 (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)
// Debido a que el manejo de memoria puede ser un dolor, en Xcode 4.2 y iOS 4 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
// utilizar ARC, no se debe de utilizar retain, release o autorelease.
MyClass *arcMyClass = [[MyClass alloc] init];
// ... código utilizando arcMyClass
// Sin ARC, necesitarás llamar: [arcMyClass release] luego de terminar de 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'
@property (weak) MyClass *weakVar; // 'weak' no adueña el objeto. El conteo de 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:
__strong NSString *strongString; // Por defecto. La variables de retenida en memoria hasta que se salga del ámbito.
__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
[Wikipedia Objective-C](http://es.wikipedia.org/wiki/Objective-C)
[Programming with Objective-C. Libro PDF de Apple](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf)
[iOS For High School Students: Getting Started](http://www.raywenderlich.com/5600/ios-for-high-school-students-getting-started)