{tecnologia, conceitos, negócios, idéias, práticas, .NET, ruby, osx, ios e algo mais}
21/05/2012
Antes de irmos para o próximo passo dentro do desenvolvimento iOS vamos começar a trabalhar um pouco o objective-c. (confira todos os posts sobre iOS)
Vamos criar uma classe para servir como model para nossa aplicação.
Criar uma classe em objective-c não é nada diferente do que já vimos aqui nos outros projetos. Vamos criar os nossos dois arquivos .h e .m assim como nos outros projetos.
Para efeito de estudos vamos criar uma aplicação para computar os gastos que fazemos na rua (o cafezinho, o almoço, o jornal, etc, etc).
Depois de criar um projeto(Single View Application mesmo), vamos adicionar um novo arquivo ao projeto, uma classe objective-c:
Essa nossa classe vai ser algo parecido com:
1 #import <Foundation/Foundation.h>
2 #import <UIKit/UIKit.h>
3
4 @interface Gastos : NSObject
5 {
6 NSMutableArray* gastos;
7 }
8
9 -(void)addGastoFromString: (NSString*) valorGasto;
10 -(int)totalDeGastos;
11 -(NSDecimalNumber*) somaDosGastos;
12 @end
O que essa classe vai fazer? Ela possui um array que nada mais é que um array dos valores dos gastos. Repare que este é um NSMutableArray, ou seja conseguiremos adicionar valores independente do tamanho do array.
Reparem que assim como em .NET tudo "herda" de Object aqui nossa classe herda de NSObject. Por ser a classe base da maioria das classes em objective-c ela provê uma série de comportamentos aos objetos (muito além do ToString, GetType e GetHashCode no .NET). Confira a documentação de NSObject aqui. É de NSObject por exemplo que vem o método alloc que utilizamos na maioria das nossas classes.
Temos 3 métodos um que iremos implementar: Na linha 9 é um método que irá adicionar um gasto a partir de uma string. Na linha 10 é apenas um método para obtermos quantos gastos foram realizados e na linha 11 uma soma dos gastos realizados.
A implementação da nossa classe é bastante simples também:
1 #import "Gastos.h"
2
3 @implementation Gastos
4
5 -(id)init{
6 gastos = [[NSMutableArray alloc] init];
7
8 return self;
9 }
10 -(void)addGastoFromString:(NSString *)valorGasto{
11 NSDecimalNumber* valor = [[NSDecimalNumber alloc] initWithFloat: [valorGasto floatValue]];
12
13 [gastos addObject:valor];
14 }
15 -(int)totalDeGastos{
16 return gastos.count;
17 }
18 -(NSDecimalNumber*) somaDosGastos{
19 NSDecimalNumber *sum = [gastos valueForKeyPath:@"@sum.floatValue"];
20
21 return sum;
22 }
23 @end
Vamos lá: nas linhas 5 até 9 temos o "construtor" da nossa classe. O que fazemos é alocar e iniciar nosso NSMutableArray. Retornamos o próprio objeto no "construtor". Nas linhas 10 a 14 temos o método que recebe uma string (vinda da interface gráfica) e criamos um NSDecimalNumber, iniciando com o valor como float.
(confesso que eu fiz algumas pesquisas e não encontrei uma forma muito canônica de manipular valores decimais e monetários, então estou usando assim a princípio)
Nas linhas 18 até 22 temos o método que faz a soma dos nossos gastos. Esse método é bastante curioso e interessante. Ele faz uso de um recurso chamado Collection operators. Basicamente usa-se um operador: @sum, @avg, @max, @min, @count e outros(veja todos). O que fazemos então é somar o floatValue de cada um dos elementos e retornamos isso em um NSDecimalNumber.
A interface desta nossa app será bastante simples (iremos evoluí-la em posts futuros). Vamos criar algo parecido com isso:
Para que o botão fique parecido com isso selecione a propriedade type do nosso UIButton:
A implementação disso é bastante tranquila também, já que a lógica toda está na classe Gastos. Veja o .h do nosso ViewController como ficou:
1 #import <UIKit/UIKit.h>
2 #import "Gastos.h"
3
4 @interface ViewController : UIViewController
5 {
6 Gastos* gastos;
7 }
8
9 -(IBAction)addGasto:(id)sender;
10
11 @property (nonatomic,retain) IBOutlet UILabel* totalDosGastos;
12 @property (nonatomic,retain) IBOutlet UILabel* numeroDeGastos;
13 @property (nonatomic,retain) IBOutlet UITextField* valorDoGasto;
14 @end
Tranquilo né? Uma action que será disparada pelo botão e três outlets que serão ligados aos elementos da nossa ui: UITextfield e os dois UILabel.
E a implementação do nosso ViewController fica assim:
1 #import "ViewController.h"
2 #import "Gastos.h"
3
4 @interface ViewController ()
5 @end
6
7 @implementation ViewController
8
9 @synthesize valorDoGasto;
10 @synthesize numeroDeGastos;
11 @synthesize totalDosGastos;
12
13 - (void)viewDidLoad{
14 [super viewDidLoad];
15
16 gastos = [[Gastos alloc]init];
17 }
18
19 -(void)addGasto:(id)sender{
20 [gastos addGastoFromString: valorDoGasto.text];
21 valorDoGasto.text = @"";
22
23 numeroDeGastos.text = [NSString stringWithFormat:@"%i", [gastos totalDeGastos]];
24
25 totalDosGastos.text = [[gastos somaDosGastos]stringValue];
26 }
27
28 //MÉTODOS GERADOS
29 - (void)viewDidUnload{
30 [super viewDidUnload];
31 }
32 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
33 return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
34 }
35 @end
Nas linhas 9 até 11 sintetizamos nossas propriedades, ou seja, os outlets que declaramos. Na linha 16 nós iniciamos nosso variável gastos. Fazemos isso da maneira padrão com alloc e init. Nas linhas 19 até 26 temos nosso addConta onde realizamos toda lógica do nosso controller: linha 20 adicionamos o valor do campo de texto aos gastos, linha 21 limpamos o nosso campo texto. obtemos o número de gastos que já adicionamos para exibir no label. Linha 23 formatamos a string com o total de gastos. E na linha 25 obtemos o somatório dos gastos e colocamos no label da interface.
Rodando nossa app teremos:
Estamos avançando a bons passos no conhecimento do iOS. Com essa nossa classe já podemos imaginar implementar algum tipo de persistência para estes dados(Core Data, alguma API de serviço externo, etc) e com isso tornar nossa aplicação mais usável. Também abrimos uma brecha para a necessidade de começar a criar navegações, formatações e até internacionalização de nossas aplicações.
Começamos a ver coisas interessantes que é a manipulação de valores financeiros (e percebemos que temos muito mais para explorar nesse sentido).
A idéia é começar a avançar em nevegação nos próximos posts, mas pode ser que façamos uma pausa para internacionalizar, formatar e tratar erros e detalhes de interface :D
Não sei se alguém que lê isso aqui está de fato brincando com iOS, mas a cada momento fico mais confortável com a plataforma com o um todo (e olhem que não estou fazendo nada além do que um estagiário faria :P)
O código deste projeto já está no github também: https://github.com/vquaiato/ios-blog-samples/tree/master/somatorioDeContas
Abração, Vinicius Quaiato.