Como criar uma aplicação simples para iPhone – Parte 1 de 3

O iPhone é uma grande plataforma de desenvolvimento para desenvolvedores independentes. Nunca foi tão fácil vir com uma ideia única, codifica-la e disponibiliza-la a milhões de clientes em potencial. Dada as possíveis dúvidas que podem surgir para começar a desenvolver uma aplicação para o iPhone, este tutorial tem o objetivo de ser um passo a passo para criar uma aplicação simples para o iOS.

Ao invés de focar nos detalhes ou em apenas um tópico, iremos criar uma aplicação inteiramente funcional do zero. No final das três partes do tutorial, teremos visto muitas áreas do desenvolvimento para iPhone, e você estará pronto para se aprofundar no tema.

Enquanto estivermos criando essa aplicação, iremos cobrir alguns dos tópicos mais comuns do desenvolvimento para iPhone:

  • O que você precisa para começar a desenvolver para iPhone
  • Como armazenar os dad0s de sua aplicação em um modelo
  • Com ousar TableViews – incluindo adição e remoção de linhas
  • Como criar uma visão detalhada de uma linha
  • Como suportar as orientações Retrato e Paisagem
  • Como usar os Controladores de navegação
  • Como usar um Selecionador de imagens
  • Como usar controles comuns como campos de textos, botões e visualizadores de imagens
  • Como adicionar ícones e imagens padrão
  • Bonus: Como manipular operações de execução longa

Na primeira parte dessa série de três, cobriremos como carregar nossa modelos com uma lista de insetos e exibi-los em um tableview.

Esse tutorial se destina a desenvolvedores iOS iniciantes, porém assume que você seja familiarizado com Objective-C e programação em geral. Se você for novo em Objetivo-C, recomento a leitura do artigo Introdução ao Objective-C em primeiro lugar.

O que você precisa

Em primeiro lugar, para desenvolver para iPhone, você precisa de um Mac. Quase todo Mac  pode ser usado, desde que tenha poder de processamento suficiente para rodar a última versão do Mac OS, o Snow Leopard. Mas se você estiver procurando pelo caminho mais barato,  pode usar um Mac Mini, que funciona relativamente bem como máquina de desenvolvimento.

Em seguida, você precisa de uma cópia do Xcode, o IDE para desenvolvimento da Apple. Se ainda não possui, registre-se grátis na iPhone Dev Center e baixe uma cópia do Xcode.

Se você quiser, pode assinar o programa pago para desenvolvedores do iPhone que permite que você distribua suas aplicações na App Store, mas se quiser apenas testar o desenvolvimento para iOS a conta gratuita servirá bem.

Se você for levar a sério o desenvolvimento para iOS, provavelmente irá querer um dispositivo físico (iPhone/iPhone 4/iPod Touch/iPad). É verdade que você pode fazer muito dos testes com o simulador, mas existem algumas APIs que não funcionam nele, e você precisa de um dispositivo físico para executar os testes.

Olá, Table View!

Iremos começar usando um dos controles mais comuns do iPhone – o TableView. Você provavelmente já viu a TableView em muitas aplicações, abaixo segue alguns exemplos:

De qualquer forma, nossa primeira tela na aplicação terá uma dessas tabelas, para exibir a lista de insetos.

Vamos começar indo em File\New Project no XCode, escolhendo Application sob o item iPhone OS, Navigation-based Application na lista a direita e clicando em “Choose…”:

Nomeie o projeto como ScaryBugs e clique em Save. E antes de fazer qualquer coisa, vamos ver o que temos até agora. na barra de ferramentas no tipo da tela escolha simulador na lista e vá para Build\Build and Run. Se tudo correr bem, você deve ver a seguinte tela no seu simulador:

Como você pode ver, nós já temos um projeto funcional para iniciar desde que escolhemos o modelo Navigation-based Application. Não iremos nos aprofundar nesse modelo pois isso está além do escopo desse tutorial, mas apenas observe que temos um tableview vazio configurado para nós e pronto para uso – apenas teremos que preenche-lo com os dados.

Agora vamos criar uma classe para manter o registro de nossos insetos.

O modelo de dados da aplicação: Organização

Observe como existe uma hierarquia de pastas na seção Groups & Files do Xcode:

O modelo escolhido vem com vários grupos – Classes, Outras fontes, Recursos, etc. Esses grupos são usados apenas para propósitos organizacionais, assim sinta-se livre para muda-los como você quiser. Em nosso caso, iremos ter vários arquivos nesse projeto, assim vamos organizar as coisas um pouco.

Em primeiro lugar, renomeie o grupo chamado “Classes” para “View Controllers”. Você pode fazer isso clicando com o botão direito no nome do grupo, escolhendo a opções “Rename” e digitando “View Controllers”.

Agora clique com o botão direito sobre o projeto “ScaryBugs” em Groups & Files, clique em “Add/New Group”. Dê o nome “Model” ao grupo, porque iremos adicionar algumas classes para nosso modelo de dados nesse grupo.

Antes de começarmos, vamos falar sobre como iremos organizar as coisas:

  1. ScaryBugData: Conterá o nome do inseto.
  2. ScaryBugDoc: Conterá a imagem e a miniatura dela.

A razão pela qual iremos configurar as coisas dessa forma é tornar mais fácil seguir esse tutorial, onde iremos começar a salvar nossos dados no disco, implementando compartilhamento de arquivo, e o que for preciso.

O modelo de dados da aplicação: Implementação

Ok, então vamos começar. Dê um clique com o botão direito no grupo Model e clique em “Add\New File…”. Sob o item iPhone OS escolha “Cocoa Touch Class”, e em seguida “Objective-C class”, certificando-se que o item “Subclass of NSObject” esteja selecionado, e clique em Next:

Nomeie o arquivo como ScaryBugData.m, certificando-se que “Also create ScaryBugData.h” esteja selecionado, e clique em Finish. Se tudo correr bem, seu Groups & Files deve se parecer com isso agora:

Agora é hora de criar nossa classe ScaryBugData. Substitua o conteúdo do arquivo ScaryBugData.h pelo seguinte:

#import <Foundation/Foundation.h>

@interface ScaryBugData : NSObject {
    NSString *_title;
    float _rating;
}

@property (copy) NSString *title;
@property  float rating;

- (id)initWithTitle:(NSString*)title rating:(float)rating;

@end

Essa é bem fácil de entender – apenas declaramos um objeto com duas variáveis de instância – uma string para o nome do inseto e um float para a nota que daremos a ele.

Também declaramos uma propriedade para cada variável, e definimos um inicializador para a classe.

Mude para o arquivo ScaryBugData.m e substitua seu conteúdo pelo seguinte:

#import "ScaryBugData.h"

@implementation ScaryBugData
@synthesize title = _title;
@synthesize rating = _rating;

- (id)initWithTitle:(NSString*)title rating:(float)rating {
    if ((self = [super init])) {
        _title = [title copy];
        _rating = rating;
    }
    return self;
}

- (void)dealloc {
    [_title release];
    _title = nil;
    [super dealloc];
}

@end

Novamente, é bem simples. Nós sintetizamos nossas propriedades, criamos nosso inicializador para preencher nossas variáveis de instância com os parâmetros passados e liberamos nossas variáveis.

Isso é tudo para ScaryBugData. Agora siga os mesmos passos descritos acima para criar outra subclasse de NSObject, dessa vez chamada ScaryBugDoc.

Substitua o conteúdo de ScaryBugDoc.h pelo seguinte:

#import <Foundation/Foundation.h>

@class ScaryBugData;

@interface ScaryBugDoc : NSObject {
    ScaryBugData *_data;
    UIImage *_thumbImage;
    UIImage *_fullImage;
}

@property (retain) ScaryBugData *data;
@property (retain) UIImage *thumbImage;
@property (retain) UIImage *fullImage;

- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage;

@end

Nada de particular a notar aqui – apenas a criação de algumas variáveis de instâncias e propriedades e um inicializador.

Substitua o conteúdo de ScaryBugData.m pelo seguinte:

#import "ScaryBugDoc.h"
#import "ScaryBugData.h"

@implementation ScaryBugDoc
@synthesize data = _data;
@synthesize thumbImage = _thumbImage;
@synthesize fullImage = _fullImage;

- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage {
    if ((self = [super init])) {
        _data = [[ScaryBugData alloc] initWithTitle:title rating:rating];
        _thumbImage = [thumbImage retain];
        _fullImage = [fullImage retain];
    }
    return self;
}

- (void)dealloc {
    [_data release];
    _data = nil;
    [_fullImage release];
    _fullImage = nil;
    [_thumbImage release];
    _thumbImage = nil;
    [super dealloc];
}

@end

E é isso – nosso modelo de dados está completo. É hora de criar alguns dados e exibi-los na Table View.

Um tipo diferente de lista de insetos

Primeiro, vamos configurar nossa tabela de forma que possa manipular a exibição de uma lista de ScaryBugDocs. Armazenaremos nosso ScaryBugData em um NSMutableArray, a classe de coleção que você usa para arrays que  são capazes de mudar dinamicamente de tamanho.

Faça as seguintes mudanças em RootViewController.h:

// Inside @interface
NSMutableArray *_bugs;

// After @interface
@property (retain) NSMutableArray *bugs;

Essa será a instância da propriedade da instância/variável que usaremos para manter o registro de nossa lista de insetos.

Agora vamos passar para o arquivo RootViewController.m e fazer as seguintes mudanças:

// At top of file
#import "ScaryBugDoc.h"
#import "ScaryBugData.h"

// After @implementation
@synthesize bugs = _bugs;

// Uncomment viewDidLoad and add the following inside
self.title = @"Scary Bugs";

// Uncomment shouldAutorotateToInterfaceOrientation, and modify the return statement to:
return YES;

// Replace the return statement in tableView:numberOfRowsInSection with the following:
return _bugs.count;

// Inside tableView:cellForRowAtIndexPath, add the following after "Configure the cell" but before return cell:
ScaryBugDoc *doc = [_bugs objectAtIndex:indexPath.row];
cell.textLabel.text = doc.data.title;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.imageView.image = doc.thumbImage;

// Add inside dealloc
[_bugs release];
_bugs = nil;

Aqui finalmente temos alguma coisa interessante para discutir.

Em primeiro lugar note que configuramos uma propriedade própria chamada “title” para a string “Scary Bugs”. Essa propriedade é uma propriedade especial dos controladores. Quando o Navigation Controller exibe um controlador, mostra o que estiver na propriedade “title” na barra de titulo. Dessa forma, ao configurar essa propriedade, devemos ver “Scary Bugs” no topo da janela.

Em seguida, observe que retornamos yes em shouldAutorotateToInterfaceOrientation, que diz ao iOS que devemos ser capazes de suportar todas as orientações – Retrato e Paisagem. Como essa classe é uma UITableViewController, isso é tudo o que temos que fazer – o view irá ser rotacionado automaticamente.

Depois, quando estivermos construindo uma Table View você sempre tem que sobrecarregar numberOfSectionsInTableView e numberOfRowsInSection para dizer ao iOS quantas seções e linhas você irá exibir na tabela. Teremos apenas uma seção, de forma que não temos que fazer nada pois o modelo está pronto para retornar 1 seção. Para as linhas, retornamos o número de objetos em nossa array de insetos.

Finalmente, implementamos tableView:cellForRowAtIndexPath, que é provavelmente o método  mais importante a ser implementado quando criamos um Table View. Aqui,  você configura a célula que será exibida em uma linha em particular. O iOS chamará esse método uma vez para cada linha.

Vamos dar uma olhada nesse método, já que é particularmente importante:

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

    // Configure the cell.
    ScaryBugDoc *doc = [_bugs objectAtIndex:indexPath.row];
    cell.textLabel.text = doc.data.title;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.imageView.image = doc.thumbImage;

    return cell;
}

As primeiras duas linhas chamam uma função chamada “dequeueReusableCellWithIdentifier” para tentar retornar uma célula reutilizável. Do que se trata tudo isso:

Bem, é uma otimização de performance importante. Mantenha em mente que Table Views podem conter um grande número de linhas, mas apenas algumas delas são exibidas na tela de cada vez. Assim ao invés de criar uma nova célula a cada vez que um novo ciclo de linhas esteja na tela, o OS pode aumentar a performance pelo reuso de uma célula que já foi criada, mas foi rolada para fora da tela.

Então é para isso que dequeueReusableCellWithIdentifier é chamada. Se não houver uma célula disponível, apenas criamos uma nova célula. Você pode criar suas próprias células, ou usar a padrão. Em nossa caso, o padrão funciona bem, assim apenas escolhemos ele pela configuração do estilo UITableViewCellStyleDefault.

Se estiver curioso para saber os diferentes padrões de célula para o Table View, vá para a seção “Standard Styles for Table-View Cells” em Table View Programming Guide.

Finalmente, configuramos a célula pelo ajuste de textLabel e imageView (que estão disponíveis com o estilo padrão).

Acredite ou não, isso é tudo que precisamos fazer! Agora precisamos configurar alguns dados para a tabela.

Fotos dos insetos

Mas naturalmente precisaremos de algumas imagens de insetos para isso. Você pode pesquisar na Internet e encontrar algumas, ou baixar as essas Fotos de insetos encontradas em stock.xchng.

Após baixar os arquivos ou obtê-los por conta própria, arraste-os para o grupo Resources do nosso projeto Xcode. Quando a janela pop-up aparecer, certifique-se que “Copy items into destination group’s folder (if needed)” esteja marcado e clique em Add.

Agora abra ScaryBugsAppDelegate.m e faça as seguintes alterações:

// At top of file
#import "ScaryBugDoc.h"
#import "RootViewController.h"

// At beginning of application:didFinishLaunchingWithOptions
ScaryBugDoc *bug1 = [[[ScaryBugDoc alloc] initWithTitle:@"Potato Bug" rating:4 thumbImage:[UIImage imageNamed:@"potatoBugThumb.jpg"] fullImage:[UIImage imageNamed:@"potatoBug.jpg"]] autorelease];
ScaryBugDoc *bug2 = [[[ScaryBugDoc alloc] initWithTitle:@"House Centipede" rating:3 thumbImage:[UIImage imageNamed:@"centipedeThumb.jpg"] fullImage:[UIImage imageNamed:@"centipede.jpg"]] autorelease];
ScaryBugDoc *bug3 = [[[ScaryBugDoc alloc] initWithTitle:@"Wolf Spider" rating:5 thumbImage:[UIImage imageNamed:@"wolfSpiderThumb.jpg"] fullImage:[UIImage imageNamed:@"wolfSpider.jpg"]] autorelease];
ScaryBugDoc *bug4 = [[[ScaryBugDoc alloc] initWithTitle:@"Lady Bug" rating:1 thumbImage:[UIImage imageNamed:@"ladybugThumb.jpg"] fullImage:[UIImage imageNamed:@"ladybug.jpg"]] autorelease];
NSMutableArray *bugs = [NSMutableArray arrayWithObjects:bug1, bug2, bug3, bug4, nil];
RootViewController *rootController = (RootViewController *) [navigationController.viewControllers objectAtIndex:0];
rootController.bugs = bugs;

Aqui nós apenas usamos o inicializador de ScaryBugDoc para criar quatro insetos, passando o titulo, a nota e as imagens para cada um. Nós adicionamos eles ao NSMutableArray e configuramos eles em nossa Table View.

Falando nisso, podemos obter um ponteiro para o RootViewController já que sabemos que ele é o primeiro controlador na pilha de navegação. Existem outras maneiras que podemos obter um ponteiro, mas essa é a mais fácil.

E é isso. Compile e execute sua aplicação, e se tudo correr bem, você deve ver uma lista de insetos em sua tabela.

Para onde ir a partir daqui?

No próximo artigo da série, veremos como criar um view com detalhes de cada inseto de modo que possamos editar e votar em cada um.

Traduzido de http://www.raywenderlich.com/1797/how-to-create-a-simple-iphone-app-tutorial-part-1