Mostrando postagens com marcador Xcode. Mostrar todas as postagens
Mostrando postagens com marcador Xcode. Mostrar todas as postagens

sábado, 31 de março de 2012

iOS: UITableView

Olá povo,

Depois de estudar por algumas vezes a programação para a plataforma iOS, resolvi escrever uma série de posts sobre o assunto. Como eu já fiz um "Hello World" e um exemplo básico de tratamento de evento (aqui e aqui respectivamente) vou começar falando do componente UITableView. Esse componente serve para exibir informações em uma lista.
Vamos começar criando um novo projeto no XCode. Selecione File > New > New Project... Na janela que for exibida, selecione Empty Application. Depois preencha os campos conforme a imagem abaixo.

Clique em Next e depois selecione em que diretório deseja salvar o projeto e clique em Create. Será criado um projeto vazio com a estrutura mostrada abaixo:
Neste momento o projeto não faz nada, então vamos criar a primeira tela que exibirá uma lista de nomes. Para tal, clique com o botão direito sobre o projeto e selecione New File...
Selecione UIViewController subclass e clique em Next. No campo Class, preencha com ListagemViewController e em Subclass of, coloque UITableViewController. Clique em Next e em seguida, Create. Criada a classe que representará a primeira tela da aplicação vamos alterar o NGAppDelegate para instanciar nossa tela. No arquivo .h adicione a propriedade do tipo UINavigationController. Ela servirá para abrirmos uma outra tela e já controlar o fluxo entre elas.
#import <UIKit/UIKit.h>

@interface NGAppDelegate : 
  UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) 
  UIWindow *window;

@property (strong, nonatomic) 
  UINavigationController *navegador;

@end
No arquivo .m já foram criados alguns métodos pelo template do XCode, mas só vamos mexer no application:didFinishLaunchingWithOptions.
#import "NGAppDelegate.h"
#import "ListagemViewController.h"

@implementation NGAppDelegate

@synthesize window = _window;
@synthesize navegador;

- (BOOL)application:(UIApplication *)application 
  didFinishLaunchingWithOptions:(NSDictionary *)opts
{
  self.window = [[UIWindow alloc] initWithFrame:[
    [UIScreen mainScreen] bounds]];

    
  ListagemViewController *lista = 
    [[ListagemViewController alloc] init];

  navegador = [[UINavigationController alloc]
    initWithRootViewController:lista];
    
  self.window.backgroundColor = [UIColor whiteColor];
    
  self.window.rootViewController = navegador;
    
  [self.window makeKeyAndVisible];
  return YES;
}
Nesse método instanciamos a nossa tela, e em seguida instanciamos o UiNavigationController passando a nossa tela como tela "raiz", ou seja, a principal. Depois associamos o UINavigationController ao objeto UIWindow, que representa a tela do aparelho.
Neste ponto, você já pode mandar rodar a aplicação, mas não teremos nada para listar. Então vamos a implementação da nossa listagem. No arquivo ListagemViewController.h, declare um array chamado nomes, conforme abaixo:
#import <UIKit/UIKit.h>

@interface ListagemViewController : 
  UITableViewController {

  NSArray *nomes;
}

@end
Como podemos observar, nossa classe herda de UITableViewController. Essa classe implementa dois protocolos (que em Java são interfaces) UITableViewDelegate e UITableViewDataSource. O primeiro trata de eventos disparados pela lista e o segundo define métodos que irão prover informações para a lista. Ao abrirmos o arquivo, podemos notar que temos vários métodos implementados, por isso só vou colocar no código abaixo os métodos que teremos que modificar.
#import "ListagemViewController.h"

@implementation ListagemViewController

#pragma mark - View lifecycle

- (void)viewDidLoad
{
  [super viewDidLoad];
    
  self.navigationItem.title = @"Listagem";
    
  nomes = [NSArray arrayWithObjects:
    @"Nelson", @"Glauber", 
    @"Vasconcelos", @"Leal", nil];
}

// ... um monte de métodos :)

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:
  (UITableView *)tableView
{
  return 1;
}

- (NSInteger)tableView:(UITableView *)tableView 
  numberOfRowsInSection:(NSInteger)section
{
  return nomes.count;
}

- (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];
  }

  cell.textLabel.text = 
    [nomes objectAtIndex:indexPath.row];
    
  return cell;
}

@end
No método viewDidLoad, inicializamos nossa lista de nomes e alteramos o título da tela. Já no método numberOfSectionsInTableView retornamos a quantidade de sessões que a lista terá. As sessões servem para agrupar opções de uma lista, mas no nosso caso, teremos apenas uma. No método tableView:numberOfRowsInSection retornamos quantas linhas têm cada sessão, como só temos uma, retornamos a quantidade de itens do nosso array de pessoas.
O último método que alteramos foi o tableView:cellForRowAtIndexPath, ele cria um objeto UITableViewCell para cada item da lista. Para evitar a criação de muitos objetos ele tenta reaproveitar linhas que não estejam mais visíveis na tela. Isso é feito no método dequeueReusableCellWithIdentifier:CellIdentifier. Caso não haja uma linha pra reciclar, criamos uma UITableViewCell com o estilo padrão (UITableViewCellStyleDefault). Em seguida, alteramos o texto da UITableViewCell (que internamente contém um UILabel) utilizando o nosso array de nomes. Para obter a posição a ser exibida, utilizamos a propriedade row o parâmetro indexPath. Pronto! Basta rodar nossa aplicação, e o resultado deverá ficar como abaixo:
Vamos criar uma tela para exibir o item selecionado. Botão direito no projeto, New File... Selecione UIViewController subclass (como fizemos anteriormente) e clique em Next. O nome da classe será DetalheViewController e será subclasse de UIViewController. Marque a opção With XIB for user interface. Clique em Next e depois em Create.
Abra o DetalheViewController.xib e arraste um Label para a tela e faça os ajustes de posicionamento e tamanho que desejar. Em seguida, vamos criar o IBOutlet para esse label: clique com o botão direito sobre o botão, e em Referencing Outlets clique em New Referencing Outlet e arraste para o arquivo .h.
Será exibido um popup para preencher o nome do nosso Outlet. Preencha com txtDetalhe e clique em Connect. Em seguida, vou adicionar a propriedade "texto" para essa tela que será atribuída pela tela de listagem. Quando clicarmos em um item da lista, criaremos uma instância de DetalheViewController a atribuiremos essa propriedade com o item selecionado da lista. O arquivos .h e .m deverão ficar como abaixo (lembrando só listamos o que foi modificado).
#import <UIKit/UIKit.h>

@interface DetalheViewController : UIViewController

@property (weak, nonatomic) 
  IBOutlet UILabel *txtDetalhe;

@property (strong, nonatomic) NSString *texto;

@end
#import "DetalheViewController.h"

@implementation DetalheViewController
@synthesize txtDetalhe, texto;

- (void)viewDidLoad
{
    [super viewDidLoad];
    txtDetalhe.text = texto;
}
Estamos quase lá. Agora volte ao arquivo ListagemController.m implemente o método tableView:didSelectRowAtIndexPath que é o método chamado quando clicamos em um item da lista.
// Adicionar import no começo do arquivo
#import "DetalheViewController.h"

- (void)tableView:(UITableView *)tableView 
  didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  DetalheViewController *detailViewController = 
    [[DetalheViewController alloc] initWithNibName:
      @"DetalheViewController" bundle:nil];
     
  detailViewController.texto = 
    [nomes objectAtIndex:indexPath.row];

  [self.navigationController pushViewController:
    detailViewController animated:YES]; 
}
O método acima instancia nosso DetalheViewController passando o arquivo *.xib (sem a extensão), em seguida atribui a propriedade texto e utiliza o navigationController (que criamos no AppDelegate) para exibir a tela. O resultado pode ser visto abaixo:
Podemos notar que o navigation controller já coloca um botão para voltarmos para a tela anterior. Em breve devo colocar mais posts sobre iOS. Qualquer dúvida, deixem seus comentários. 4br4ç05, nglauber

quarta-feira, 30 de março de 2011

Eventos Simples no iOS

Olá povo,

Dando continuidade ao post sobre iPhone, mostrarei nesse como tratar eventos simples na plataforma iOS. Nosso exemplo constará de uma tela com uma caixa de texto e um botão. Ao clicar nesse botão, será exibida uma mensagem com o conteúdo digitado.

Inicie um novo projeto no Xcode, selecione a opção View-based Application e indique o local onde deseja salvar seu projeto juntamente com seu nome (utilizei ExemploBlog2). Um novo projeto será iniciado e começaremos nosso exemplo desenhando a tela da aplicação. Dê um duplo clique sobre o arquivo ExemploBlog2ViewController.xib que está dentro da pasta Resources. O Interface Builder será aberto para que possamos editar o arquivo.
Arraste da janela Library (se ela não estiver sendo exibida pressione Shift-Command-L): um Label, um TextField e um RoundRectButton. Altere a texto do Label e do botão dando um duplo-clique sobre eles. Na janela de propriedades (se não estiver ativa, pressione Command-1) altere a propriedade Text Input Traits > Return Key para Done. Isso servirá para quando terminarmos de digitar o texto desejado, possamos fechar o teclado virtual. Por fim, arraste os componentes de na tela deixando-os similar a figura abaixo.
Salve o arquivo e volte ao Xcode. Vamos agora declarar esses componentes no código da classe que tratará os eventos da UI. Abra o arquivo ExemploBlog2ViewController.h e deixe-o conforme abaixo.

#import <UIKit/UIKit.h>

@interface ExemploBlog2ViewController :
UIViewController {

IBOutlet UITextField* txtNome;
}

- (IBAction) doneDoTeclado;
- (IBAction) cliqueDoBotao;

@end


No arquivo .h é onde declaramos os atributos da classe (que ficam entre as chaves) e as assinaturas de métodos (após a chave de fechamento e a diretiva @end). No código acima, declaramos um UITextField que representará a caixa de texto que definimos no InterfaceBuilder. Notem que antes da declaração, colocamos o texto IBOutlet, que é necessário para que possamos interligar essa variável ao componente definido no Interface Builder.

Logo abaixo declaramos dois métodos, o primeiro servirá para fechar o teclado virtual e o segundo servirá para tratar o clique do botão. A implementação desses métodos fica no arquivo com exetnsão .m. Abra o arquivo ExemploBlog2ViewController.m e deixe-o de acordo com o código abaixo:

#import "ExemploBlog2ViewController.h"

@implementation ExemploBlog2ViewController

- (IBAction) doneDoTeclado {
[txtNome resignFirstResponder];
}

- (IBAction) cliqueDoBotao{
[self doneDoTeclado];
NSString *mensagem = [[NSString alloc]
initWithFormat:@"Você digitou %@", txtNome.text];

UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Informação"
message:mensagem
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[mensagem release];
}

- (void)dealloc {
[txtNome release];
[super dealloc];
}

@end


O iOS (sistema operacional do iPhone/iPad/iPod Touch) utiliza uma cadeia de "respondedores" de eventos. Ao entrar em uma caixa de texto, o teclado virtual passa a tratar os eventos da caixa de texto. Para reatribuir o controle ao TextField chamamos o método resignFirstResponder.
No método do clique do botão, chamamos o método doneDoTeclado, para que, se o usuário clicar no botão sem clicar no Done do teclado, o teclado virtual desapareça. Em seguida criamos uma string (representada pela classe NSString) para concatenar a mensagem que desejamos com o texto digitado.
Notem que foi utilizado o método alloc seguido pelo método initWithFormat. Diferentemente de Java, no Objective-C temos que alocar e desalocar a memória utilizada pelo objeto. O método alloc chamado a partir da classe faz a alocação e o método release (como usamos mais abaixo) faz a liberação. Objective-C não tem o conceito de construtores, por isso são usados métodos com prefixo init para inicializar o objeto.
A classe que exibirá a mensagem é a UIAlertView, a qual inicializamos um objeto passando o título do diálogo, a mensagem, um objeto que trate o clique do botão do diálogo, o texto do primeiro botão, e por último o texto de mais botões que você desejar.
Como você deve ter notado, chamadas de método são feitas usando a notação diferente das linguagens basedas em C (como Java, C#, C++). Ele utiliza a notação In-Fix que coloca palavras antes de cada parâmetro para explicar para que serve. No código acima é fácil identificar para que serve cada parâmetro para criar o UIAlertView. Criado o diálogo, o exibimos chamando o método show.

Por fim, o método dealloc deve liberar todos os recursos alocados pela tela. No nosso caso, estamos liberando a memória alocada para o TextField.

A parte de código está pronta. Falta agora fazer a ligação entre o arquivo .xib do InterfaceBuilder com esse código. Volte para o InterfaceBuilder e vamos fazer essa ligação. Selecione o TextField e a partir da janela Connections (se não estiver sendo exibida, Command-2) clique em New Referencing Outlet e arraste para o File's Owner conforme a figura abaixo. Na lista que for exibida, selecione txtNome.



Faça agora a ligação arrastando o evento Did End on Exit para o File's Owner e na lista que será exibida selecione doneDoTeclado. Agora selecione o botão e faça agora a ligação arrastando o evento Touch Up Inside para o File's Owner, e na lista que for exibida selecione cliqueDoBotao.

Feito isso, volte para o Xcode e pressione o botão Build and Run. O resultado será semelhante as figuras abaixo.




Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

terça-feira, 8 de fevereiro de 2011

Hello World iPhone

Olá povo,

A muito tempo que deveria ter escrito esse post. Passei 2010 entre iPhone e Android graças ao meu mestrado, e hoje vou apresentar pra vocês como começar a desenvolver aplicativos para o iOS, o sistema operacional dos dispositivos móveis da Apple (iPhone, iPad e iPod touch).
Para começo de conversa, precisamos de um computador que rode o Mac OS X. Pelas vias legais, você deve ter um Macbook, iMac, Mac Pro ou Mac mini. Entretanto você pode recorrer a um bom e velho Hackintosh ou instalar uma máquina virtual com o sistema operacional da Apple.
O kit de desenvolvimento está disponível no site da Apple (developer.apple.com) e pode ser baixado livremente, bastando apenas fazer o registro gratuitamente. Ele só é "um pouquinho" grande, tem cerca de 3.6GB, então se for baixar via dial-up, esqueça! :) (não que eu acredite que um desenvolvedor ainda acesse internet assim). A instalação é bem simples, basta seguir o assistente. A última versão do SDK exige a versão 10.6.4 ou superior do Mac OS, e uma recomendação é que sua máquina tenha 2GB de memória pra trabalhar bem.

As principais ferramentas do SDK são: Xcode, Interface Builder e os Emuladores do iPhone e iPad.
A primeira, é a IDE, onde criamos e gerenciamos nossos projetos, além de escrever o código fonte, compilar e executar a aplicação. O Interface Builder é um editor visual onde podemos criar as telas da aplicação e fazer a associação de componentes visuais para atributos da classe (criada no Xcode), e de eventos disparados por componentes a métodos declarados no código fonte. Quando o código fonte é compilado, ele pode ser testado no emulador. Na versão atual, temos emuladores para iPhone e iPad, porém funcionalidades como acelerômetro e GPS não estão disponíveis neles. Sendo assim, para testar esse tipo de funcionalidade precisamos de um aparelho real, e para tal, você deve pagar por uma licença de desenvolvedor. Com esse licença, você obtém uma assinatura que deve ser usada em suas aplicações de modo a instalá-las no aparelho. Mas se você já fez o Jailbreak no seu iPhone, podem testar sem licença mesmo :)

Nosso exemplo fará um bom e velho HelloWorld. Para começãr, execute o Xcode e vá até o menu File > New project. Será exibida a tela abaixo:

O Xcode disponibiliza alguns templates que criam a estrutura básica do projeto dependendo de sua funcionalidade. Utilizaremos o template "View based Application", selecione-o e clique em Choose. Em seguida, dê o nome ao seu projeto (eu coloquei ExemploBlog) e clique em ok.
O nosso projeto será exibido no Xcode conforme a imagem abaixo.


No lado direito é exibido o conteúdo de uma pasta na parte superior e o conteúdo do arquivo na parte inferior. No lado esquerdo fica a estrutura do nosso projeto organizado em pastas. As principais são as pastas Classes e Resources. Na primeira ficam os arquivos de código fonte, que assim como em C e C++ fica divido em arquivos de cabeçalho (.h) e de implementação (.m). Já as imagens e os arquivos que definem a interface gráfica (chamados de NIBs mas com extensão .xib) ficam no diretório Resources.

Vamos resumir como um programa iOS começa. Ele inicia com um arquivo chamado main.m (que fica na pasta Other Resources) que lê um arquivo que tem o mesmo nome do projeto e com extensão .plist. Nesse arquivo, existe a definição de qual será o NIB principal da aplicação. Nesse NIB constam: uma referência para a classe que implementa UIApplicationDelegate; uma instância de UIWindow que representa a tela do aparelho; e opcionalmente uma referência para UIViewController que trata os eventos de interface gráfica.

Vejam que nosso projeto tem a classe ExemploBlogAppDelegate. Que tem o seguinte código:

// Arquivo .h
#import <UIKit/UIKit.h>

@class ExemploBlogViewController;

@interface ExemploBlogAppDelegate : NSObject
<UIApplicationDelegate>{

UIWindow *window;
ExemploBlogViewController *viewController;
}

@property (nonatomic, retain) IBOutlet
UIWindow *window;
@property (nonatomic, retain) IBOutlet
ExemploBlogViewController *viewController;

@end

// Arquivo .m
#import "ExemploBlogAppDelegate.h"
#import "ExemploBlogViewController.h"

@implementation ExemploBlogAppDelegate

@synthesize window;
@synthesize viewController;

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions {

[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];

return YES;
}

- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
@end

O arquivo .h acima define: de qual estamos herdando; (opcionalmente) quais interfaces ele implementa; as declarações de atributos; e declarações de métodos. Nesse arquivo estão definidos dois atributos: window e viewController. Em Objective-C temos o conceito de propriedades muito conhecido dos desenvolvedores Delphi e C#. Não vamos entrar em detalhes sobre isso, mas pensem nelas como sendo atalhos para métodos GET e SET.
Ainda no código acima, temos o método application:didFinishLaunchingWithOptions que é chamado quando a aplicação é carregada, e quando isso ocorre, a View (que define uma tela da aplicação) do ViewController (que trata os evento dessa tela) é adicionada a Window, e logo em seguida, torna-se visível. Ao final, o método dealloc, libera a memória alocada pela tela.
Como você pode ver, o ViewController declarado é do tipo ExemploBlogViewController (que está declarada nos arquivos de mesmo nome com extensão .h e .m). TodoViewController tem uma View associada que dispara eventos para ele. No nosso projeto, essa View está definida no arquivo ExemploBlogViewController.xib. Dê um duplo clique nesse arquivo e será aberto o InterfaceBuilder.

O InterfaceBuilder é composto por quatro janelas principais: Main, View, Attributes e Library. A primeira exibe a estrutura do arquivo; a segunda, é o editor visual onde adicionamos os componentes e podemos ter uma idéia de como ficará a tela; na janela attributes podemos alterar as propriedades dos componentes da tela; na última, temos todos os componentes que podemos adicionar à tela.


Adicione um Label da janela Library para a janela Window. Dê um duplo-clique no componente adicionado e digite um novo valor para o texto. Selecione o Label, e na janela Attributes altere a cor do texto (você consegue achar né? :). Depois altere o tamanho do texto. Por fim, salve as alterações e volte para o Xcode.

Clique no Build and Run, e o emulador do iPhone iniciará com nossa aplicação executando! \o/


Que beleza hein!? Um HelloWorld sem digitar nenhuma linha de código! :)
No próximo post vamos falar um pouco sobre Objective-C e veremos como tratar eventos de componentes.
Espero que tenham gostado. Dúvidas e melhorias, deixem seus comentários.

4br4ç05,
nglauber