"CheckBoxes" para iPhone
02 July 2008
Despues de buscar por toda la documentación algun control tipo checkBox decidi crear una aplicación sencilla que simule el comportamiento de un checkBox usango dos graficos: encendido y apagado. El ejemplo que desarrollaremos sera una lista de compras en un UITableView:
Para empezar crearemos una nuevo proyecto del tipo "Navigation-Based Application" que llamaremos ListaDeCompras, quiero resaltar que en este ejemplo no usaremos Interface Builder porque me parece que quedara mucho mas claro hacerlo todo mediante programacion:
Nos crearemos un nuevo archivo tipo UIViewController al que llamaremos ListaDeComprasViewController, por ahora no haremos nada con este archivo.
Al crear el proyecto se creo por defecto un archivo ListaDeComprasAppDelegate con la extension .h y .m, entremos a ListaDeComprasAppDelegate.h para inicializar nuestra ventana y su navigationController :
[cpp]
@interface ListaDeComprasAppDelegate : NSObject
{
UIWindow *window;
UINavigationController *navigationController;
}
@end
[/cpp]
Ahora en ListaDeComprasAppDelegate.m aňadimos la vista del controlador a nuestra la ventana dentro del metodo applicationDidFinishLaunching.
Al inicializar el navegador vemos que se asigna un initWithRootViewController , en este caso una instancia de ListaDeComprasViewController que sera la vista que se mostrara al iniciar la aplicacion:
[cpp]
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
ListaDeComprasViewController *controler = [[ListaDeComprasViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:controler];
[controler release];
[window addSubview: navigationController.view];
}
[/cpp]
Ahora trabajemos con los archivos ListaDeComprasViewController .h y .m respectivamente. En ListaDeComprasViewController.h inicializaremos un tableView para mostrar nuestros datos y un array que contendra nuestra lista de compras de la siguiente manera:
[cpp]@interface ListaDeComprasViewController : UIViewController
{
NSMutableArray *listaDeCompras;
UITableView *slTableView;
}
@end[/cpp]
Ahora, en el archivo ListaDeComprasViewController.m es donde debemos cargar toda nuesta vista, recordemos que no estamos usando IB asi que debemos usar el metodo loadView.
Empezamos creando una vista inicial a la que llamaremos contentView, luego crearemos un tableView que añadiremos a la vista principal.
Para el arreglo crearemos objetos con 2 variables: item y cantidad y un booleano que nos indique si el objeto esta seleccionado o no.
[cpp]- (void)loadView
{
listaDeCompras = [[NSMutableArray alloc] init];
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = contentView;
[contentView release];
self.view.autoresizesSubviews = YES;
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Huevos", @"item", @"Una docena", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Leche", @"item", @"1 litro", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Azucar", @"item", @"5 kilos", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
slTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
slTableView.delegate = self;
slTableView.dataSource = self;
slTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
slTableView.autoresizesSubviews = YES;
slTableView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[slTableView reloadData];
[self.view addSubview:slTableView];
}
[/cpp]
Ahora para poder usar nuestro tableView usamos los metodos de UITableViewDelegate y UITableViewDataSource.
En el metodo cellForRowAtIndexPath insertamos los valores del array para cada celda y con un if-else determinamos si aparecera la imagen de apagado o encendido dependiendo de nuestro valor booleano. Y en el metodo didSelectRowAtIndexPath es donde este valor ira cambiando cada vez q seleccionemos una celda.
[cpp]- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [listaDeCompras count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *newValue = [NSNumber numberWithBool:![[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"completado"] boolValue]];
[[listaDeCompras objectAtIndex:indexPath.row] setObject:newValue forKey:@"completado"];
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableString *cellValue = [NSMutableString stringWithCapacity:[[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"item"] length] + [[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"cantidad"] length] + 3];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ListaDeComprasCell"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"ListaDeComprasCell"] autorelease];
}
[cellValue setString:[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"item"]];
[cellValue appendString:@" ("];
[cellValue appendString:[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"cantidad"]];
[cellValue appendString:@")"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.text = cellValue;
if([[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"completado"] boolValue])
{
cell.image = [UIImage imageNamed:@"encendido.png"];
cell.textColor = [UIColor grayColor];
}
else
{
cell.image = [UIImage imageNamed:@"apagado.png"];
cell.textColor = [UIColor blackColor];
}
cell.showsReorderControl = YES;
return cell;
}
[/cpp]
Finalmente hacemos dos cambios mas en el archivo infoplist borramos el nombre del archivo main.nib en Main nib file base name porque no estamos usandolo y dentro del archivo main.m hacemos el siguiente cambio para que nuestro proyecto llame a ListaDeComprasAppDelegate:
[cpp]
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"ListaDeComprasAppDelegate");
[pool release];
return retVal;
}
[/cpp]
Las imagenes de encendido y apagado las agregamos a la raiz del proyecto o podemos crear un directorio especial para nuestras imagenes, en ambos casos funciona de la misma manera. Espero que este ejemplo les haya servido y cualquier pregunta no duden en escribir.
Para empezar crearemos una nuevo proyecto del tipo "Navigation-Based Application" que llamaremos ListaDeCompras, quiero resaltar que en este ejemplo no usaremos Interface Builder porque me parece que quedara mucho mas claro hacerlo todo mediante programacion:
Nos crearemos un nuevo archivo tipo UIViewController al que llamaremos ListaDeComprasViewController, por ahora no haremos nada con este archivo.
Al crear el proyecto se creo por defecto un archivo ListaDeComprasAppDelegate con la extension .h y .m, entremos a ListaDeComprasAppDelegate.h para inicializar nuestra ventana y su navigationController :
[cpp]
@interface ListaDeComprasAppDelegate : NSObject
{
UIWindow *window;
UINavigationController *navigationController;
}
@end
[/cpp]
Ahora en ListaDeComprasAppDelegate.m aňadimos la vista del controlador a nuestra la ventana dentro del metodo applicationDidFinishLaunching.
Al inicializar el navegador vemos que se asigna un initWithRootViewController , en este caso una instancia de ListaDeComprasViewController que sera la vista que se mostrara al iniciar la aplicacion:
[cpp]
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
ListaDeComprasViewController *controler = [[ListaDeComprasViewController alloc] init];
navigationController = [[UINavigationController alloc] initWithRootViewController:controler];
[controler release];
[window addSubview: navigationController.view];
}
[/cpp]
Ahora trabajemos con los archivos ListaDeComprasViewController .h y .m respectivamente. En ListaDeComprasViewController.h inicializaremos un tableView para mostrar nuestros datos y un array que contendra nuestra lista de compras de la siguiente manera:
[cpp]@interface ListaDeComprasViewController : UIViewController
{
NSMutableArray *listaDeCompras;
UITableView *slTableView;
}
@end[/cpp]
Ahora, en el archivo ListaDeComprasViewController.m es donde debemos cargar toda nuesta vista, recordemos que no estamos usando IB asi que debemos usar el metodo loadView.
Empezamos creando una vista inicial a la que llamaremos contentView, luego crearemos un tableView que añadiremos a la vista principal.
Para el arreglo crearemos objetos con 2 variables: item y cantidad y un booleano que nos indique si el objeto esta seleccionado o no.
[cpp]- (void)loadView
{
listaDeCompras = [[NSMutableArray alloc] init];
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = contentView;
[contentView release];
self.view.autoresizesSubviews = YES;
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Huevos", @"item", @"Una docena", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Leche", @"item", @"1 litro", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
[listaDeCompras addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"Azucar", @"item", @"5 kilos", @"cantidad", [NSNumber numberWithBool:NO], @"completado", nil]];
slTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
slTableView.delegate = self;
slTableView.dataSource = self;
slTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
slTableView.autoresizesSubviews = YES;
slTableView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[slTableView reloadData];
[self.view addSubview:slTableView];
}
[/cpp]
Ahora para poder usar nuestro tableView usamos los metodos de UITableViewDelegate y UITableViewDataSource.
En el metodo cellForRowAtIndexPath insertamos los valores del array para cada celda y con un if-else determinamos si aparecera la imagen de apagado o encendido dependiendo de nuestro valor booleano. Y en el metodo didSelectRowAtIndexPath es donde este valor ira cambiando cada vez q seleccionemos una celda.
[cpp]- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [listaDeCompras count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *newValue = [NSNumber numberWithBool:![[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"completado"] boolValue]];
[[listaDeCompras objectAtIndex:indexPath.row] setObject:newValue forKey:@"completado"];
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableString *cellValue = [NSMutableString stringWithCapacity:[[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"item"] length] + [[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"cantidad"] length] + 3];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ListaDeComprasCell"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"ListaDeComprasCell"] autorelease];
}
[cellValue setString:[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"item"]];
[cellValue appendString:@" ("];
[cellValue appendString:[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"cantidad"]];
[cellValue appendString:@")"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.text = cellValue;
if([[[listaDeCompras objectAtIndex:indexPath.row] objectForKey:@"completado"] boolValue])
{
cell.image = [UIImage imageNamed:@"encendido.png"];
cell.textColor = [UIColor grayColor];
}
else
{
cell.image = [UIImage imageNamed:@"apagado.png"];
cell.textColor = [UIColor blackColor];
}
cell.showsReorderControl = YES;
return cell;
}
[/cpp]
Finalmente hacemos dos cambios mas en el archivo infoplist borramos el nombre del archivo main.nib en Main nib file base name porque no estamos usandolo y dentro del archivo main.m hacemos el siguiente cambio para que nuestro proyecto llame a ListaDeComprasAppDelegate:
[cpp]
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"ListaDeComprasAppDelegate");
[pool release];
return retVal;
}
[/cpp]
Las imagenes de encendido y apagado las agregamos a la raiz del proyecto o podemos crear un directorio especial para nuestras imagenes, en ambos casos funciona de la misma manera. Espero que este ejemplo les haya servido y cualquier pregunta no duden en escribir.

Comentarios recientes
No consigo que se guarde el archivo. Podriais decirme si se tiene que configurar algo en el simulador del iphone para poner un directorio donde guarde el archivo txt? He seguido todos los pasos y despues de Añadir no puedo recuperar esa informacion. Gracias
Deja un comentario