jul 15

Hace algún tiempo os comenté como detectar cambios en propiedades mediante el KVO (Key-Value Observing) hoy veremos como hacer lo mismo con notificaciones.

La idea del ejemplo es la siguiente: Tenemos un objeto A de una clase X, del que queremos ser avisados cuando una propiedad sea modificada, para ello avisaremos a otro objeto B, para que éste último realize alguna acción. Para ello usaremos notificaciones, el objeto A enviará una notificación cuando cambie su propiedad y el objeto B estará pendiente de dichas notificaciones.

Veamos como hacer esto desde el código, primero nos creamos una función que será la encargada de enviar las notificaciones. Usamos el centro de notificaciones por defecto de nuestra aplicación y el método postNotificationName:object: para enviar la notificación. Los parámetros son un string para el nombre de la notificación y el objeto que envía la notificación.

#pragma mark -
#pragma mark Notification methods
 
- (void)sendNumberPadPressedNotification {
     [[NSNotificationCenter defaultCenter] postNotificationName:@"number pad pressed" 
                                                         object:self];
}

Después sólo tenemos que llamar a esta función cada vez que queramos notificar del evento o cambio producido, por ejemplo si pulsamos un botón.

#pragma mark -
#pragma mark Notification methods
- (IBAction)ceroButtonPushed:(id)sender {
     [input setString:[numberFormater stringFromNumber:[NSNumber numberWithFloat:0.00]]];
     coma = NO;
     decimal = 1;
     [self sendNumberPadPressedNotification];
}

En la última línea llamamos a nuestro método y la notificación es enviada, en este ejemplo se usa para avisar de que input fue cambiado.

Esto es todo lo que necesita nuestro objeto A (el que avisa del cambio o evento). Veamos ahora el código para el objeto B (el que quiere ser avisado).

Lo primero que tenemos que hacer es registrar el objeto B en el centro de notificaciones para poder recibirlas, obviamente nos tenemos que registrar en el mismo centro de notificaciones que el objeto A, en este caso el centro por defecto.

Usamos para ello el método addObserver:selector:name:object: los parámetros son: el objeto a registrar, un selector del método que queremos ejecutar al recibir la notificación, el nombre de la notificación para la que queremos ser avisados y el objeto sobre el que queremos ser avisado, éste último puede ser nil o el objeto en concreto, para poder diferenciar quien manda la notificación en caso de tener más de un objeto enviando la misma notificación.

 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
 - (void)viewDidLoad {
     [super viewDidLoad];
     numberPadController = [[GenericNumberPad alloc] initWithNibName:@"GenericNumberPad"
     	  						      bundle:[NSBundle mainBundle]
							       frame:CGRectMake(20, 190, 280, 216)];
     [[NSNotificationCenter defaultCenter] addObserver:self 
                                              selector:@selector(numberPadPressed)
						  name:@"number pad pressed" object:nil];
     [[self view] addSubview:[numberPadController view]];
 }

Cómo veis en el código, el nombre de la notificación es el mismo que se usó en el objeto A. Ya sólo queda que realiceis vuestras acciones en el método que indicasteis a la hora de registrar el objeto B.

#pragma mark -
#pragma mark Notification methods
 
- (void)numberPadPressed {
     [importLabel setText:[numberPadController input]];
}

En este ejemplo se ha usado para actualizar una etiqueta con el valor de la variable input, cada vez que ésta era cambiado.

VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
jul 05

En este post veremos como podemos obtener archivos que nuestra aplicación cree durante su ejecución, ésto nos puede ser útil cuando queremos comprobar que se han creado correctamente o cuando queremos obtener la base de datos que estemos creando desde la aplicación.

Para ello usaremos Xcode desde la ventana “organizer”, que podéis abrir desde el menú ventana. Desde el organizer y con vuestro iPhone conectado tendremos acceso a las aplicaciones instaladas en éste, sólo tendremos acceso a nuestras aplicaciones. Localizamos nuestra aplicación y pulsamos sobres el triángulo de la izquierda para ver su contenido.

Ahora deveríamos estar viendo un icono de una caja, el típico icono de package de las instalaciones.

Sólo nos queda arrastrar este icono al escritorio y obtendremos una carpeta con el contenido de las carpetas Documents, Library y tmp de nuestra aplicación y los archivos que contienen.

Con esto y el post anterior que nos mostraba como copiar un archivo a la carpeta documents, ya podemos acceder a cualquier archivo que creemos en nuestra aplicación.

Otra cosa a tener en cuenta es que si añadimos o modificamos archivos de esta carpeta, y arrastramos la carpeta de vuelta a nuestra aplicación en la ventana organizer, podremos meter cualquier archivo que queramos en las carpetas de la aplicación.

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
jul 05

Con este post mostraré como podemos copiar un archivo, que previamente hemos añadido a nuestro proyecto, a la carpeta documentos de nuestra aplicación. La idea es la de poder inicializar de una manera rápida y cómoda la base de datos, algún archivo de configuración que tengamos o cosas por el estilo que tenemos que guardar en la carpeta documentos de la aplicación porque durante ejecución sufrirán cambios realizados por el usuario, evitando así tener que crearlos desde el código de la aplicación.

Primero, lo que tenemos que hacer es añadir ese archivo al proyecto para tener acceso a él desde el código cuando se ejecuta la aplicación. Añadid el archivo a la carpeta “Resources” del proyecto.

Una vez tenemos el archivo en el proyecto, podemos añadir el código para copiar el archivo a la carpeta documentos, añadid el siguiente código en vuestro AppDelegate, podéis crearos una función nueva para inicializar los archivos que necesiteis, o añadirlo directamente al init del AppDelegate.

// Copy init.sqlite from resources to the Documents folder in bundle
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"data.sqlite"];
if(![[NSFileManager defaultManager] fileExistsAtPath:storePath])
{
	NSString *filePath = [[NSBundle mainBundle] pathForResource:@"init" ofType:@"sqlite"];
	NSData *myData = [NSData dataWithContentsOfFile:filePath];
	if (![myData writeToFile:storePath atomically:YES]) {
		NSLog(@"ERROR writting the starting database");
	}
}

En el ejemplo anterior usamos un archivo, init.sqlite, como base de datos inicial para nuestra aplicación y guardamos el mismo archivo bajo el nombre de data.sqlite en el directorio documentos de nuestra aplicación. Daos cuenta también de que usamos un if para comprobar si el archivo existe o no, de forma que sólo se ejecutará la primera vez que ejecutemos la aplicación, ésto es así, para que cuando nuestro usuario vaya añadiendo datos no se los borremos y carguemos siempre la base de datos inicial. Si durante las pruebas queréis volver a obtener el archivo original, eliminad la aplicación del iPhone o del iPhone Simulator.

El método applicationDocumentsDirectory es la siguiente función que nos devuelve la ruta a la carpeta.

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
	return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
VN:F [1.9.8_1114]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.8_1114]
Rating: +1 (from 1 vote)
Tagged with:
jun 13

Cuando trabajamos con tablas (UITableView), podemos crear celdas personalizadas a través de Interface Builder o crearlas directamente desde el código, el problem aparece cuando cambiamos el color de fondo por otro que no sea blanco y sólo creamos la celda cuando vamos a mostrar datos, pero no hacemos nada para las celdas vacías.

Nos encontramos con algo como esto

Esto nos pasa porque sólo creamos la celda con fondo cuando tenemos datos para rellenar, tenemos dos opciones para solucionarlo:

  • Programar nuestro código de forma que cuando rellenamos la tabla se consideren los casos en que no hay datos, es decir cargar una celda pero sin las etiquetas o imágenes.
  • Poner a todas las celdas el mismo color de fondo antes de mirar nada.

Con esta segunda opción, es la más rápida, podemos darle el mismo color a todas las celdas, la única manera de hacerlo sin crearnos una celda personalizada, sin nada más que el fondo para celdas vacías desde Interface Builder, es hacerlo dentro del código:

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
 
    // Configure the cell.
    [[cell contentView] setBackgroundColor:[UIColor colorWithRed:0 green:128/255.f blue:0 alpha:1]];    
    return cell;
}

La linea que nos interesa es la que llama al método setBackgroundColor:, con esta linea es la que le damos el color que queremos. Daros cuanta de que usamos [cell contentView], tenemos que cambiar el color de la contentView, esta es la clave de que no se pueda hacer desde Interface Builder directamente cuando añadimos una tabla, desde la tabla no podemos acceder al contenido de la celda sin añadir explicitamente las celdas.

Con esa linea obtendremos algo cómo esto

VN:F [1.9.8_1114]
Rating: 5.0/5 (2 votes cast)
VN:F [1.9.8_1114]
Rating: +1 (from 1 vote)
Tagged with:
jun 13

No se si alguna vez os ha pasado que para limpiar vuestro simulador (iPhone Simulator) en lugar de borrar aplicación por aplicación, hicisteis un reset y después os encontrasteis conque desaparecieron todas las fotos XD, que esperabais ;).

Bien, pues tanto si hicisteis un reset intencionadamente, sin querer, o para limpiar toda los datos y apps innecesarios que se acumulan al hacer pruebas y más pruebas aquí van un par de trucos para añadir nuevas fotos:

Fotos que tenemos en archivos:

Para añadir fotos que ya tenemos en alguna otra carpeta solo teneis que copiarlas en la siguiente ruta.

~/Users/<usuario>/Library/Application Support/iPhone Simulator/3.1.3/Media/DCIM/100APPLE

Donde <usuario> es vuestro nombre de usuario, si no y quizá tengáis que cambiar también la versión del SDK por la que estéis usando.

Nota: He visto varias rutas diferentes, que empiezan diractamente por ~/Library/Application Support/iPhone Simulator/…, la idea es que tenéis que estar dentro de la carpeta del iPhone Simulator, y añadir las fotos en Media/DCIM/100APPLE, si esta última carpeta no esta crearla.

Variante: También podéis abrir Safari dentro del simulador y arrastrar el archivo a la pagina web de éste, luego haced click y no solteis el botón hasta que os aparezca la opción de salvar la imagen. Se os añade a la librería de fotos.

Fotos desde internet:

En caso de que queráis añadir nuevas fotos desde internet, por ejemplo desde google images, solo tenéis que hacer como antes (en la variante) y pulsar sobre la imagen, aguantando el botón hasta que os deje guardarla.

VN:F [1.9.8_1114]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.8_1114]
Rating: 0 (from 0 votes)
Tagged with:
preload preload preload