martes, 6 de julio de 2010

Capitulo 4 - Chapter 4 - Spot-On Game

Introduccion


El juego Spot-On pone a proeba tus reglejos al requerir tocar los puntos antes de que desaparescan. Los puntos se hacen pequenos a medida de que se van moviendo, entre mas tiempo el punto esta en la pantalla mas pequeno se hacen y por lo mismo son mas dificiles de tocar. El juego comienza en el nivel uno y avazamos al siguiente nivel cuando llegamos a tocar 10 puntos.
Entre mas alto es el nivel los puntos se moveran mas rapipo haciendo el juego mas competitivo. Cuando tocamos los puntos el juego hara un sonido y el punto se tornara verde y desaparecera. Los jugadores reciviran puntuacion por cada ves que toquen los puntos. Presicion es muy importante por que cada vez que toques el punto y falles refuciras 20 puntos.
La puntucion esta ubicada hacia esquina izquierda de la pantalla. El jugador comenzara con 3 vidas, las cuales estaran en la parte inferior izquierda de la pantalla. Si el punto desaparece de la pantalla la aplicacion hara un sonido de que perdiste una vida. El jugador ganara 1 vida por cada vez que pase un nive.
Cuando el jugador pierde toda sus vidas el juego esta terminado.


Descripción de la tecnología

Por cada punto animado, vamos a usar un UIImageView para mostrar un Custom Image ( Imagen modificada). Nosotros cambiamos esta imagen cuando un punto es tocado por la configuración de las propiedades del UIImageView hacia una nueva UIImage. En SpotOnViewController, nosotros vamos a implementar el manejo del tacto en nuestro juego. Vamos a procesar el evento multi-tacto, permitiendo al jugador tocar los puntos simultáneamente.
El metodo touchesBegan describe desde UIView utilizado para obtener táctil del iPhone. Este metodo recibe pointer hacia los Objetos UITouch cuando la pantalla es tocada. También retraeremos las coordenadas de cada vez que el usuario toque la pantalla, y usar esa información para determinar si el usuario toco el punto o no.
Vamos a usar el Core Animation framework para animar los puntos haciendas mover, haciendolos pequenos hasta desaparecer.
Como pueden ver UIImageView trae incorporado un metodo de animación, el cual provee acceso facil hacia una animación basica. También vamos a accesar al bajo CALayer( CORE ANIMATION LAYER) para realizar animaciones mas complejas que no son proveídas por UIImageView.
Sonido es agregado a la aplicación usando el AVFoundation framework. AVAudioPlayer son usados para hacer playback .wav files almacenados en el iphone. Cada archivo esta asociado a un objeto AVAudioPlayer para controlar el playback del archivo. El metodo NSObject performSelector:withObject:afterDelay: nos permite llamar funciones después de un especifico retraso ( En segundos). Vamos a usar esto para agregar los primeros 3 puntos al nuevo juego en el segundo intervalo.

WORKING ON THE REST

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



jueves, 13 de mayo de 2010

Capitulo 2 - Chapter 2 - TipCalculator

Hola amigos, aqui tenemos el segundo capitulo del Curso espero que lo disfruten .
Algo que les recomiendo es que escriban el codigo por ustedes mismos en vez de usar la funcion de copiar y pegar. Esto les ayudara a entender exactamente lo que estan haciendo si tiene una pregunta dejen su comentario por favor y tambien delen rate al video y comentarios
Gracias

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




  1. 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.

  2. 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)
  3. Abrimos el archivo Controller.h y escribimos el codigo que se encuentra adjuntado en el blog.
  4. 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
  5. Seleccionamos el nuevo objeto creado en la ventana y abrimos la ventana Inspector para cambiar la clase de NSObject a Controller.
  6. Despues cambiamos a Connections Tab, aqui veran los Outels y las accion.
  7. Van a conectar los Outlets con sus respectivos objeto como esta mostrado en el video
  8. 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
  9. Ahora vamos a colocar el segundo pedazo de codigo en el archivo Controller.m en la carpeta Classesc de Xcode
Les voy a explicar que significa el paso 8 y nueve.
Lo que estos dos pasos hacen es que al momento de que el usuario seleciona el text field o el Slider un mensaje es enviado al Objeto Controller para que ejecuete el metodo CalculateTip:



Codigo de la clase Controller.h


// 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