martes, 6 de julio de 2010
Capitulo 4 - Chapter 4 - Spot-On Game
jueves, 20 de mayo de 2010
Capitulo 3 - Chapter 3 - Busquedas Favoritas en Twitter - Favorite Twitter Searches
- Abrir Xcode y crear un nuevo proyecto con el nombre de FavoriteTwitterSearchs, le damos click a MainWindow.xib para abrir interface builder
- 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.
- Después arrastramos dos Text Fields hacia la ventana de la aplicación.
- Seleccionamos el primer Text Field. En el Tab de Atributos del Inspector, agregamos este siguiente texto " Enter query expression here" en el PlaceHolder Field.
- En el segundo Text Field hacemos lo mismo con la diferencia de que escribiremos "Tag your search".
- 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.
- Ahora agarramos un View desde la libreria, lo expandamos hasta que cubra la aplicacion debajo de los Text Fields.
- Seleccionamos este View y abrimos Inspector, vamos al atributes tab y le damos click al background y esto abrira la ventana Colors.
- 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.
- 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
- 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 ".
- 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"
- 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 .
- Abrimos el archivo Controller.h y ponemos el Codigo numero uno que esta adjuntado al final del Capitulo.
- Una vez que terminamos de editar Controller.h, guardamos y abrimos el archivo MainWindow.xib en Interface Builder.
- Despues de esto agarramos un Object de Library y los ubicamos en la ventana MainWindow.xib.
- 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.
- 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.
- 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,
- Grabamos y Cerramos Interface Builder
- Ahora vamos a usar la segunda parte del Codigo en el archivo Controller.m
- Grabamos y ejecutamos (Build and Run)
// 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
jueves, 13 de mayo de 2010
Capitulo 2 - Chapter 2 - TipCalculator
Calculadora de Propinas ( Tip Calculator )
La Aplicación que vamos a construir continuación calcula y muestra la propina de que deja en un restaurante de acuerdo al monto total.
La aplicación calculara el 10%, 15% y 20%. El usuario también podrá especificar un porcentaje modificado al mover el Slider ( Resbalador).
La aplicación usa varias características de object-oriented Objective-C incluyendo declaración de clases conocidas como interfaces in Objetive-C.
Vas a aprender también palabras claves básicas de Objective-C y sintaxis al momento de que escribas el código y este responda cuando el programa interactúe al momento de usar el GUI.
Revisión de la Tecnología usada en esta aplicación
En este siguiente capitulo introduciré algunas capacidades de Objective-C incluyendo objetos(Objects), clases(Classes), interfaces (Interfaces) y herencias(inheritance ).
El código de Objective-C requiere varios tipos de datos ( Data Type), Operadores (Operators), control de declaraciones( Control Statements) y palabras claves (Keywords). Tu vas a declarar variables (Variables) que correspondan al componente GUI. Tu vas a declarar e implementar métodos, vas usar mensajes para invocar los métodos de un objeto.
Para armar el evento vamos a necesitar agarrar y arrastrar las habilidades de Interface Interface Builder a la conexión de cada componente GUI y el método debe responder a las acciones de los eventos.
Construyendo la Aplicación.
1. Abrir Xcode
2. Seleccionar Window-based Aplicacion temple
3. Ir a carpeta Resource y dar doble click en el file MainWindow.xib, esto abrirá el programa Interface Builder.
4. Ahora agarrar y arrastrar un Text Field de la ventana library hacia la ventana Window.
5. Selecciona tu Text Field y ve a la ventana Inspector.
6. En la propiedad del texto la dejamos en 0.00
7. Quita el Check (Palomilla) de la caja Clear When Editing Begins
8. Ahora localiza la propiedad Keyboard debajo de Text Input Traits, esta propiedad muestra el Number Pad ya que lo único que necesitamos son dígitos
9. Luego agarramos y arrastramos un Label de la ventana de Library en la ventana de la aplicación, le damos doble click al label para cambiar el texto y ponen Total Bill ( Cuenta Total )
10. Pueden ajustar el tamaño del label de acuerdo a su gusto y podrán notar que habrán líneas cortadas al momento de mover el label esto les indicara la posición que esta ocupando el Babel
11. Agarramos y arrastramos 3 labels mas debajo de el Text Field con los nombres de 10%, 15% y 20%.
12. Seleccionar el primer Text Field que crearon y presionar Command+ D, esto duplicara el Text Field, creen 6 y colóquenlas debajo de los Labels: 10%, 15% y 20% como muestra el video
13. Seleccionar los nuevos Text Fields ir a la ventana Inspector bajar hasta la propiedad Control y quitar el Check de la opción Enabled. Le daremos Atributo de Text 0.00
14. Duplicar el primer Label 2 veces y colocar cada uno a lado de las dos filas un Label con el nombre de Tip y el otro Total.
15. Agarrar y arrastra un nuevo Label debajo del tercer label como esta mostrado en el video, luego cambiamos el atributo del label a 15%.
16. Ahora crearemos un Slider ( Delizante ) con el cual el usuario tendra la capacidad de cambiar el porcentaje de Tip(Propinas) que se otorgara, agarramos y arrastramos desde la Library ( El Slider sera la barrita con el circulo al centro), este lo ubicamos al lado izquierdo del Label 15%.
17. Seleccionamos el Slider y vamos a la ventana del Inspector y donde dice Minimum a 0.00, Maximum a 0.30 e Initial a 0.15
18. Ahora que el Slider esta configurado agregamos un nuevo label a la derecha de el Slider con la Propiedad “Custom”.
19. Para Completar nuestra aplicación necesitamos agregar 2 Labels y Text Fields debajo del Slider, Primero el Label con el atributo de Tip, luego creamos un Text Field junto a el , ahora un nuevo Text Field, Un nuevo Label con el atributo de Total y un Nuevo Label.
Estos son los paso para crear la Interface de la Aplicación. La aflicción esta creada pero ahora tenemos que darle funcionabilidad.
Para esto necesitaremos escribir cierto código en Xcode, es preferible que el codigo lo escriban ustedes en vez de cortar y pegar ya que de esa forma se ira familiarizando con el.
Dandole Funcionalidad a la aplicacion
-
Ahora regresamos a Xcode y vamos a File, New File , Aquí Estara remarcado Cocoa Touch Class, junto a ese estara un File llamado Objective-C , ese va a ser el que vamos a escoger ese y nos aseguramos que dejajo de el este en la subclass este como NSObject.
- Con esto se habran creado dos archivos en el Xcode/Resources los cuales tendran el nombre de Controller.h y Controller.m, pero los movemos a clases( CLasses)
- Abrimos el archivo Controller.h y escribimos el codigo que se encuentra adjuntado en el blog.
- Vamos a Interface Builder a la ventana Library y escogemos un objeto llamado Object. Este no es un Componente GUI por lo tanto no va a ir a la ventana de la aplicacion si no que va a ir a la ventana MainWindow.xib. ( Esta Mostrado en el video
- Seleccionamos el nuevo objeto creado en la ventana y abrimos la ventana Inspector para cambiar la clase de NSObject a Controller.
- Despues cambiamos a Connections Tab, aqui veran los Outels y las accion.
- Van a conectar los Outlets con sus respectivos objeto como esta mostrado en el video
- Selecionamos ahora el Text Field en la parte superior de la aplicacion y vamos a Atribute Window y damos click en el el Connection Tab, aqui vamos a la opcion de events( Eventos es lo que vamos a usar para decirle a la aplicacion que hacer cuando el usuario seleccione el Text Field) vas a seleccionar el evento Editing Changed y desde el circulo arrastramos hasta el MainWindow Object( Mostrado en el video) dice Controller en el MainWindow.xib
- Ahora vamos a colocar el segundo pedazo de codigo en el archivo Controller.m en la carpeta Classesc de Xcode
// Fig. #.#: Controller.h
// Controller class for the Tip Calculator app.
// Methods defined in Controller.m.
#import
@interface Controller : NSObject
{
// outlets
IBOutlet UITextField *billField;
IBOutlet UITextField *tipFieldTen;
IBOutlet UITextField *tipFieldFifteen;
IBOutlet UITextField *tipFieldTwenty;
IBOutlet UITextField *tipFieldCustom;
IBOutlet UITextField *totalFieldTen;
IBOutlet UITextField *totalFieldFifteen;
IBOutlet UITextField *totalFieldTwenty;
IBOutlet UITextField *totalFieldCustom;
IBOutlet UILabel *customPercentLabel;
IBOutlet UISlider *customPercentSlider;
NSString *billTotal; // string for the "Bill Total" field
} // end instance variable declarations
- (IBAction)calculateTip:(id)sender; // calculates the tips
@end
Codigo de la clase Controller.m
// Controller.m
// Controller class for the tip calculator app.
#import "Controller.h"
@implementation Controller // begin implementation of Controller
// called after all the GUI elements have been loaded
- (void)awakeFromNib
{
[billField becomeFirstResponder]; // display keyboard for billField
} // end method awakeFromNib
// called when the user touches a key or button
- (IBAction)calculateTip:(id)sender
{
static BOOL toggle = YES; // was this method trigger by the user?
// the user touched the keypad or moved the Slider
if (toggle)
{
toggle = NO; // this method will next be called programmatically
// retrieve the string in billField
NSString *billFieldText = billField.text;
// convert billFieldText to a float
float newTotal = [billFieldText floatValue];
// retrieve the slider value (between 0 and 0.3)
float customTipPercent = customPercentSlider.value;
// determine if billField generated the event
if (sender == billField)
{
// delete key pressed
if (billFieldText.length < billTotal.length)
billTotal = [NSString stringWithFormat:@"%.02f",
newTotal / 10];
else // new digit entered
billTotal = [NSString stringWithFormat:@"%.02f",
newTotal * 10];
// update billField with the properly formatted number
billField.text = billTotal;
// update newTotal with the new value
newTotal = [billTotal floatValue];
// calculate the tips for 10, 15 and 20%
float tenTip = newTotal * 0.10;
float fifteenTip = newTotal * 0.15;
float twentyTip = newTotal * 0.20;
// set the values for the "Tip" fields
tipFieldTen.text = [NSString stringWithFormat:@"%.02f", tenTip];
tipFieldFifteen.text =
[NSString stringWithFormat:@"%.02f", fifteenTip];
tipFieldTwenty.text =
[NSString stringWithFormat:@"%.02f", twentyTip];
// set the values for the "Total" fields
totalFieldTen.text =
[NSString stringWithFormat:@"%.02f", newTotal + tenTip];
totalFieldFifteen.text =
[NSString stringWithFormat:@"%.02f", newTotal + fifteenTip];
totalFieldTwenty.text =
[NSString stringWithFormat:@"%.02f", newTotal + twentyTip];
} // end if
// determine if customPercentSlider generated the event
else if (sender == customPercentSlider)
{
// the "Custom" slider was moved
// round the value to a whole number
int percentage = (int)(customTipPercent * 100);
// update the label with the new percentage followed by %
customPercentLabel.text =
[NSString stringWithFormat:@"%i%%", percentage];
// convert percentage back to float and assign to Slider's value
float newSliderValue = ((float) percentage) / 100;
customPercentSlider.value = newSliderValue;
// slider Thumb moved; update customTipPercent
customTipPercent = newSliderValue;
} // end else
// calculate customTip
float customTip = customTipPercent * newTotal;
// update tipFieldCustom with the new custom tip value
tipFieldCustom.text = [NSString stringWithFormat:@"%.02f",
customTip];
// update totalFieldCustom
totalFieldCustom.text =
[NSString stringWithFormat:@"%.02f", customTip + newTotal];
} // end if
else // the method was called programmatically
{
toggle = YES; // the method will next be called by user interaction
}
} // end method calculateTip:
@end // Controller's implementation