jueves, 20 de mayo de 2010

Capitulo 3 - Chapter 3 - Busquedas Favoritas en Twitter - Favorite Twitter Searches


Hola Amigos con este seria el capitulo numero 3 de mi curso espero q disfruten este proyecto, por favor comente y dejen su email para que cada vez que un nuevo curso sea subido les llegue un mensaje informandoles que ya esta disponible.
Bueno ahora dejenme explicar esta aplicacion.
Esta aplicacion permite al usuario guardar sus busquedas favoritas en twitter . Tambien le dejara al usuario seguir rapido y facil sus Tweets.
Una vez mas vamos a dividir en 2 partes este capitulo. La primera se tratara de como construimos la ventana de la aplicacion y en la segunda le daremos funcionabilidad a la aplicacion.


Construyendo la Aplicación.



  1. Abrir Xcode y crear un nuevo proyecto con el nombre de FavoriteTwitterSearchs, le damos click a MainWindow.xib para abrir interface builder
  2. Agarramos un Label desde la Libreria y lo nombramos Favorite Twitter Searches, en el inspector incrementamos el Font Size a 18, Centramos el Label en la parte superior de la ventana usando Layout> Alignment>Align Horizontal Center in Container.
  3. Después arrastramos dos Text Fields hacia la ventana de la aplicación.
  4. Seleccionamos el primer Text Field. En el Tab de Atributos del Inspector, agregamos este siguiente texto " Enter query expression here" en el PlaceHolder Field.
  5. En el segundo Text Field hacemos lo mismo con la diferencia de que escribiremos "Tag your search".
  6. Agarramos un Round Rect Button de la libreria en la ventana de la aplicación. En el tab de Atributos del Inspector, colocamos como titulo ( Title) Save.
  7. Ahora agarramos un View desde la libreria, lo expandamos hasta que cubra la aplicacion debajo de los Text Fields.
  8. Seleccionamos este View y abrimos Inspector, vamos al atributes tab y le damos click al background y esto abrira la ventana Colors.
  9. Damos click en el segundo tab, y seleccionamos RGB Slider de la lista. Cualquier color puede ser creado de la combinacion del rojo, verde y azul, a estos componentes se los conoce como RGB values. Escogemos un color y cerramos la ventana Color y volvemos a la ventana de la aplicacion. El colo de el View cambia el reflejo del nuevo color.
  10. Ahora agarramos un nuevo Label adentro del View y le escribimos como texto Tagged Searches. En el Inspector, Cambiamos el color a blanco si escogimos un color oscuro y centramos el texto
  11. Agarramos un nuevo Round Rect Button de la libreria hacia la parte inferior de la ventana de la aplicacion, le damos doble click y la nombramos " Clear all Tags ".
  12. Despues Agregamos a nuestra ventana de la aplicacion ( Una instancia de la clase UIScrollView), lo cual permite al usuario ir atraves el contenido si es muy grande para mostrarlo en la pantalla. La ubicacion del Scroll View sera entre el Label "Tagged Searches" y el boton " Clear all Tags"
Con esto Concluye la el diseno GUI de nuestra nueva aplicacion.

Dandole funcionabilidad a la Aplicacion

  1. Abrimos Xcode, seleccionamos la Classes y creamos una nueva clases como lo discutimos en el capitulo anterior. Asegurense de que NSObject este seleccionado en la Subclass de la lista. Le damos click a Finish .
  2. Abrimos el archivo Controller.h y ponemos el Codigo numero uno que esta adjuntado al final del Capitulo.
  3. Una vez que terminamos de editar Controller.h, guardamos y abrimos el archivo MainWindow.xib en Interface Builder.
  4. Despues de esto agarramos un Object de Library y los ubicamos en la ventana MainWindow.xib.
  5. Seleccionamos el Objeto y vamos al inspector en el Tab Identity y cambiamos el valor en la clase a Controller.
  6. Cambiamos a el Tab Connections en el inspector. aqui encontraremos 3 outlets que conectaremos con sus correspondientes GUI components.
  7. Despues vamos a conectar los eventos generados por los componentes GUI con sus correspondientes acciones. Los eventos generados en esta aplicacion son enviados por los Objetos ( Button ). Para esto seleccionamosel "Save" Button y abrimos el Tab Connection en el Inspector. En este caso usaremos el evento (Event) Touch Up Inside, desde el circulo lo arrastramos hacia el Objeto Controller en la Ventana Window y escogemos addTag: de la lista.
  8. ahora seleccionamos el boton Clear All Tags, vamos a Inspector y escogemos el evento Touch Up Side, Arrastramos hacia el objeto Controller y seleccionamos clearTags: de la lista,
  9. Grabamos y Cerramos Interface Builder
  10. Ahora vamos a usar la segunda parte del Codigo en el archivo Controller.m
  11. Grabamos y ejecutamos (Build and Run)

Controller.h

// Controller.h

// Controller class for the Favorite Twitter Searches app.

#import



// constants that control the height of the buttons and the spacing

#define BUTTON_SPACING 10

#define BUTTON_HEIGHT 40


@interface Controller : NSObject // this line is autogenerated

{

// Interface Builder outlets

IBOutlet UIScrollView *scrollView; // for scrollable favorites

IBOutlet UITextField *tagField; // text field for entering tag

IBOutlet UITextField *queryField; // text field for entering query

// stores the tag names and searches

NSMutableDictionary *tags;

// stores the Buttons representing the searches

NSMutableArray *buttons;

// stores the info buttons for editing existing searches

NSMutableArray *infoButtons;

// location of the file in which favorites are stored

NSString *filePath;

} // end instance variable declarations


- (IBAction)addTag:sender; // adds a new tag

- (IBAction)clearTags:sender; // clears all of the tags

- (void)addNewButtonWithTitle:(NSString *)title; // creates a new button

- (void)refreshList; // refreshes the list of buttons

- (void)buttonTouched:sender; // handles favorite button event

- (void)infoButtonTouched:sender; // handles info button event

@end // end Controller interface


// begin UIButton's sorting category

@interface UIButton (sorting)

// compares this UIButton's title to the given UIButton's title

- (NSComparisonResult)compareButtonTitles:(UIButton *)button;

@end // end catagory sorting of interface UIButton



Controller.m




// Controller.m

// Controller class for the Favorite Twitter Searches app.

#import "Controller.h" //this line is auto-generated


@implementation Controller //this line is auto-generated


// called when object is initialized

- (id)init

{

self = [super init]; // initialize the superclass members

if (self != nil) // if the superclass initialized properly

{

// creates list of valid directories for saving a file

NSArray *paths = NSSearchPathForDirectoriesInDomains(

NSDocumentDirectory, NSUserDomainMask, YES);

// get the first directory

NSString *dir = [paths objectAtIndex:0];

// concatenate the file name "tagsIndex.plist" to the path

filePath = [[NSString alloc] initWithString:

[dir stringByAppendingPathComponent:@"tagsIndex.plist"]];

NSFileManager *fileManager = [NSFileManager defaultManager];

// if the file does not exist, create an empty NSMutableDictionary;

// otherwise, initialize an NSDictionary with the file's contents

if ([fileManager fileExistsAtPath:filePath] == NO)

{

tags = [[NSMutableDictionary alloc] init];

} // end if

else

{

tags = [[NSMutableDictionary alloc]

initWithContentsOfFile:filePath];

} // end else

buttons = [[NSMutableArray alloc] init]; // create array

infoButtons = [[NSMutableArray alloc] init]; // create array

} // end if

return self; // if self == nil, object not initialized properly

} // end method init


// called when the GUI components finish loading

- (void)awakeFromNib

{

for (NSString *title in tags)

[self addNewButtonWithTitle:title];

} // end method awakeFromNib


// remove all buttons and populate View with favorites

- (void)refreshList

{

// remove all the buttons from the GUI

for (UIButton *button in scrollView.subviews)

[button removeFromSuperview];

[infoButtons removeAllObjects];

float buttonOffset = BUTTON_SPACING; // reset the spacing

// repopulate the scroll view with buttons

for (UIButton *button in buttons)

{

CGRect buttonFrame = button.frame; // fetch the frame of button

buttonFrame.origin.x = BUTTON_SPACING; // set the x-coordinate

buttonFrame.origin.y = buttonOffset; // set the y-coordinate

// button width is the size of the view minus padding on each side

buttonFrame.size.width =

scrollView.frame.size.width - 5 * BUTTON_SPACING;

buttonFrame.size.height = BUTTON_HEIGHT; // set the height of button

button.frame = buttonFrame; // assign the new frame to button

[scrollView addSubview:button]; // add button as a subview

// create detail button

UIButton *infoButton =

[UIButton buttonWithType: UIButtonTypeDetailDisclosure];

[infoButtons addObject:infoButton]; // add infoButton to infoButtons

// position button to the right of the button we just added

buttonFrame = infoButton.frame; // fetch the frame of infoButton

buttonFrame.origin.x = scrollView.frame.size.width - 35;

// this button is a bit shorter than normal buttons, so we adjust

buttonFrame.origin.y = buttonOffset+3;

infoButton.frame = buttonFrame; // assign the new frame

// make the button call infoButtonTouched: when it is touched

[infoButton addTarget:self action:@selector(infoButtonTouched:)

forControlEvents:UIControlEventTouchUpInside];

[scrollView addSubview:infoButton]; // add infoButton as a subview

// increase the offset so the next button is added further down

buttonOffset += BUTTON_HEIGHT + BUTTON_SPACING;

} // end for

} // end refreshList


// called when the user touches an info button

- (void)infoButtonTouched:sender

{

// get the index of the button that was touched

int index = [infoButtons indexOfObject:sender];

// get the title of the button

NSString *key = [[buttons objectAtIndex:index] titleLabel].text;

tagField.text = key; // update tagField with the button title

// get the search query using the button title

NSString *value = [tags valueForKey:key];

queryField.text = value; // update queryField with the value

} // end method infoButtonTouched:


// add a favorite search

- (IBAction)addTag:sender

{

// make the keyboard disappear

[tagField resignFirstResponder];

[queryField resignFirstResponder];

NSString *key = tagField.text; // get the text in tagField

NSString *value = queryField.text; // get the text in queryField

// test if either field is empty

if (value.length == nil || key.length == nil)

return; // exit from the method

if ([tags valueForKey:key] == nil) // test if the tag already exists

[self addNewButtonWithTitle:key]; // if not, add a new button

[tags setValue:value forKey:key]; // add a new entry in tags

tagField.text = nil; // clear tagField of text

queryField.text = nil; // clear queryField of text

[tags writeToFile:filePath atomically:NO]; //save the data

} // end method addTag:


// remove all the tags

- (IBAction)clearTags:sender

{

[tags removeAllObjects]; // clear tags

[tags writeToFile:filePath atomically:NO]; // update favorite file

[buttons removeAllObjects]; // clear buttons

[self refreshList]; // update the display

} // end clearTags:


// add a new button with the given title to the bottom of the list

- (void)addNewButtonWithTitle:(NSString *)title

{

// create a new button

UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

// give the button the title of the tag

[button setTitle:title forState:UIControlStateNormal];

// tell the button to call buttonTouched: when it is touched

[button addTarget:self action:@selector(buttonTouched:)

forControlEvents:UIControlEventTouchUpInside];

[buttons addObject:button]; // add the UIButton to the end of the array

// sort the NSMutableArray by the UIButton's titles

[buttons sortUsingSelector:@selector(compareButtonTitles:)];

[self refreshList]; // refresh the list of favorite search Buttons

// Adjust the content size of the view to include the new button. The

// view scrolls only when the content size is greater than its frame.

CGSize contentSize = CGSizeMake(scrollView.frame.size.width,

buttons.count * (BUTTON_HEIGHT + BUTTON_SPACING) + BUTTON_SPACING);

[scrollView setContentSize:contentSize];

} // end addNewButtonWithTitle:


// load selected search in web browser

- (void)buttonTouched:sender

{

NSString *key = [sender titleLabel].text; // get Button's text

// get the search and replace special characters with percent escapes

NSString *search = [[tags valueForKey:key]

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

// format the URL

NSString *urlString = [NSString stringWithFormat:

@"http://search.twitter.com/search?q=%@", search];

NSURL *url = [NSURL URLWithString:urlString];

[[UIApplication sharedApplication] openURL:url];

} // end buttonTouched

@end // end implementation Controller


// define UIButton's sorting category method

@implementation UIButton (sorting)

- (NSComparisonResult)compareButtonTitles:(UIButton *)button

{

// compare this UIButton's title to that of the given UIButton

return [self.titleLabel.text

caseInsensitiveCompare:button.titleLabel.text];

} // end method compareButtonTitles

@end // end UIButtons's sorting category



Espero que lo disfruten



12 comments:

c4r7o5 dijo...

Tu curso me a servido mucho ... Recientemente compre una iMac para poder hacer apps... pero aquí en México es difícil encontrar tutoriales o algún tipo de curso ... lo único que me gustaría un poco mas de tu curso es que subas capítulos mas seguido... pero aun así muchas gracias !!!

Raul dijo...

Genial sin duda de lo mejor que he visto.
Muchas gracias por tus aportes. Para cuando los próximos?
Un saludo!

Unknown dijo...

Muy interesante tu artículo y muy bien explicado y detallado. No puedo acceder a los anteriores (2 y 1), ¿puedes decirme como please?

Unknown dijo...

Al final de estaa pagina hay un link q dice Entradas antiguas. Alli estan los capitulos anteriores

Anónimo dijo...

Muy bien me estan gustando, ya que hay pocos sitios que te expliquen como programar para iphone en españo!! sigue asii!! cada cuanto tiempo tienes pensado en ir subiendo los capitulos??

@Apple_venezuela dijo...

Interesante no se si es porque tengo la ultima SDK, pero el text del controller.m me arroja 32 errores y 5 failed

Mariano J. Mateuci dijo...

me tira un solo warning.. quizas puedan ayudarme soy nuevo en esto, dice..

warning: no rule to process file '$(PROJECT_DIR)/Classes/controller.h' of type sourcecode.c.h for architecture i386

Si alguien me da una mano les voy a estar agradecido.. graciaaas de todas maneras.

liuba dijo...

estos tutoriales sirven para el SDK 4.0.1? o como le hago para bajar uno anterior y practicar? y ta,bien pues tu pusiste los textos de los codigos, y eso como puedo aprender a hacerlo?

EnJofre dijo...

Los ejemplos estan muy bien, pero ...
Seleccionamos el Objeto y vamos al inspector en el Tab Identity y cambiamos el valor en la clase a Controller.
Cambiamos a el Tab Connections en el inspector. aqui encontraremos 3 outlets que conectaremos con sus correspondientes GUI components.

No me aparece nada, que hago mal?

Trabajo con Xcode 3.2.5

Saludos

Unknown dijo...

EnJofre@: Primeramente gracias por seguir mi Blog.
Segundo: segun estas haciendo los pasos deben aparecer los outlets.
solamente asegurate de que en la ventana mainWindow.xib hayas seleccionado Controller.
Si deseas enviarme una impresion de tu pantalla para ver donde esta el problema.

Saludos

desoler dijo...

Hola, para cuando las siguientes entradas?, o ya no vas a actualizar mas este blog? saludos

Pascual dijo...

Hola, estoy buscando información para hacer una aplicación universal, es decir que la aplicación ejecute unas instrucciones en el ipad y otras distintas en el iphone y la verdad es que no encuentro nada, a ver si alguien me puede ayudar. Os dejo mi correo: PascualArroyo@me.com

Publicar un comentario