SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   1	
  
Desenvolvendo	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  mauricio.linhares@gmail.com	
  	
  
DESENVOLVIMENTO	
  DE	
  APLICAÇÕES	
  PARA	
  IOS	
  USANDO	
  OBJECTIVE-­‐C	
   1	
  
INTRODUÇÃO	
   2	
  
CAPÍTULO	
  1	
  -­‐	
  CONHECENDO	
  OBJECTIVE-­‐C	
   3	
  
IMAGEM	
  1	
  –	
  SELEÇÃO	
  DE	
  PROJETOS	
  NO	
  XCODE	
   3	
  
IMAGEM	
  2	
  –	
  CRIANDO	
  O	
  PROJETO	
  NO	
  XCODE	
  	
   4	
  
IMAGEM	
  3	
  –	
  VISUALIZAÇÃO	
  INICIAL	
  DO	
  PROJETO	
   5	
  
IMAGEM	
  4	
  –	
  CRIANDO	
  O	
  TARGET	
  QUE	
  VAI	
  RODAR	
  OS	
  NOSSOS	
  TESTES	
   6	
  
IMAGEM	
  5	
  –	
  ADICIONANDO	
  O	
  EXECUTÁVEL	
  DA	
  APLICAÇÃO	
  COMO	
  DEPENDÊNCIA	
  AO	
  TARGET	
  TEST	
   7	
  
IMAGEM	
  6	
  –	
  CRIANDO	
  A	
  NOSSA	
  PRIMEIRA	
  CLASSE	
  EM	
  OBJECTIVE-­‐C	
   8	
  
IMAGEM	
  7	
  –	
  CRIANDO	
  A	
  NOSSA	
  PRIMEIRA	
  CLASSE	
  EM	
  OBJECTIVE-­‐C	
   9	
  
IMAGEM	
  8	
  –	
  VISUALIZAÇÃO	
  DO	
  NAVEGADOR	
  DE	
  ARQUIVOS	
  COM	
  A	
  CLASSE	
  CONTA	
  CRIADA.	
   9	
  
LISTAGEM	
  1	
  –	
  CONTA.H	
   9	
  
LISTAGEM	
  2	
  –	
  CONTA.M	
   11	
  
LISTAGEM	
  3	
  –	
  CONTA.H	
   11	
  
LISTAGEM	
  4	
  –	
  CONTA.M	
   12	
  
CRIANDO	
  O	
  NOSSO	
  PRIMEIRO	
  TESTE	
  UNITÁRIO	
   12	
  
IMAGEM	
  9	
  –	
  CRIANDO	
  O	
  GRUPO	
  “TEST”	
   13	
  
IMAGEM	
  10	
  –	
  CRIANDO	
  A	
  CLASSE	
  DE	
  TESTES	
   13	
  
IMAGEM	
  11	
  –	
  SELECIONANDO	
  OS	
  TARGETS	
  DA	
  CLASSE	
  DE	
  TESTES	
   14	
  
IMPLEMENTANDO	
  O	
  NOSSO	
  PRIMEIRO	
  TESTE	
   14	
  
LISTAGEM	
  5	
  –	
  CONTATEST.M	
   14	
  
IMAGEM	
  12	
  –	
  ALTERANDO	
  O	
  TARGET	
  PADRÃO	
  PARA	
  TEST	
   16	
  
IMAGEM	
  13	
  –	
  DRAG	
  E	
  DROP	
  DO	
  ARQUIVO	
  “CONTA.M”	
  EM	
  TEST	
   16	
  
IMAGEM	
  14	
  –	
  INDICAÇÃO	
  DE	
  ERROS	
  DE	
  BUILD	
  DO	
  XCODE	
   17	
  
IMAGEM	
  15	
  –	
  TELA	
  DE	
  ERROS	
  NO	
  BUILD	
  DO	
  XCODE	
   18	
  
LISTAGEM	
  6	
  –	
  CONTA.H	
   18	
  
LISTAGEM	
  7	
  –	
  CONTA.M	
   19	
  
LISTAGEM	
  8	
  –	
  CONTATEST.H	
   20	
  
LISTAGEM	
  	
  9	
  –	
  CONTATEST.M	
   20	
  
CRIANDO	
  UM	
  “CONSTRUTOR”	
  PARA	
  O	
  NOSSO	
  OBJETO	
  CONTA	
   22	
  
LISTAGEM	
  10	
  –	
  CONTA.H	
  –	
  DECLARANDO	
  O	
  MÉTODO	
  INITWITHSALDO	
   22	
  
LISTAGEM	
  11	
  –	
  CONTA.M	
   23	
  
DEFININDO	
  PROPRIEDADES	
  AUTOMATICAMENTE	
  NOS	
  OBJETOS	
   23	
  
LISTAGEM	
  12	
  –	
  CONTA.H	
  COM	
  AS	
  NOVAS	
  PROPRIEDADES	
  DEFINIDAS	
   24	
  
LISTAGEM	
  13	
  –	
  CONTA.M	
  COM	
  A	
  DEFINIÇÃO	
  DAS	
  PROPRIEDADES	
  E	
  GERENCIAMENTO	
  DE	
  MEMÓRIA	
   25	
  
LISTAGEM	
  14	
  –	
  CONTATEST.M	
  COM	
  O	
  CÓDIGO	
  DE	
  GERENCIAMENTO	
  DE	
  MEMÓRIA	
   26	
  
	
  
	
   	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   2	
  
Introdução	
  
Este	
  material	
  tem	
  como	
  objetivo	
  servir	
  de	
  referência	
  para	
  o	
  curso	
  de	
  
desenvolvimento	
  de	
  aplicações	
  usando	
  Objective-­‐C	
  e	
  XCode	
  para	
  iOS,	
  o	
  sistema	
  
operacional	
  	
  para	
  dispositivos	
  móveis	
  da	
  Apple,	
  como	
  iPhones,	
  iPods	
  e	
  iPads.	
  Ele	
  
faz	
  parte	
  do	
  material	
  complementar	
  para	
  as	
  aulas	
  expositivas	
  do	
  curso	
  de	
  
desenvolvimento	
  para	
  iOS.	
  
Para	
  seguir	
  esse	
  material	
  você	
  precisa	
  de	
  um	
  computador	
  com	
  MacOS	
  e	
  XCode	
  
instalados,	
  além	
  do	
  SDK	
  para	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS.	
  O	
  material	
  
também	
  assume	
  que	
  você	
  já	
  tem	
  experiência	
  com	
  o	
  desenvolvimento	
  de	
  
software	
  em	
  ao	
  menos	
  uma	
  linguagem	
  orientada	
  a	
  objetos.	
  	
  
Conceitos	
  básicos	
  de	
  programação	
  orientada	
  a	
  objetos	
  como	
  variáveis	
  de	
  
instância,	
  métodos,	
  construtores,	
  herança,	
  encapsulamento	
  não	
  vão	
  ser	
  
explicados,	
  assume-­‐se	
  que	
  quem	
  está	
  lendo	
  o	
  material	
  já	
  tem	
  conhecimento	
  de	
  
todos	
  esses	
  conceitos	
  que	
  são	
  lugar	
  comum	
  em	
  qualquer	
  linguagem	
  de	
  
programação	
  orientada	
  a	
  objetos.	
  
Em	
  várias	
  partes	
  do	
  material	
  você	
  vai	
  encontrar	
  a	
  fala	
  “Abra	
  o	
  menu	
  contextual	
  
do	
  item	
  X”	
  ou	
  “clique	
  com	
  o	
  botão	
  direito	
  em	
  X”,	
  isso	
  quer	
  dizer	
  usar	
  o	
  botão	
  
direito	
  do	
  mouse	
  (em	
  um	
  mouse	
  comom)	
  fazer	
  “Control	
  +	
  Click”	
  no	
  item	
  
selecionado	
  ou,	
  se	
  você	
  estiver	
  usando	
  um	
  trackpad	
  multi-­‐touch,	
  clicar	
  com	
  os	
  
dois	
  dedos	
  ao	
  mesmo	
  tempo.	
  
	
   	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   3	
  
Capítulo	
  1	
  -­‐	
  Conhecendo	
  Objective-­‐C	
  
O	
  código	
  fonte	
  deste	
  primeiro	
  capítulo	
  está	
  disponível	
  em	
  -­‐	
  
https://github.com/mauricio/capitulo-­‐1-­‐curso-­‐ios	
  	
  
Objective-­‐C	
  é	
  uma	
  linguagem	
  de	
  programação	
  orientada	
  a	
  objetos	
  de	
  uso	
  geral	
  e	
  
é	
  a	
  língua	
  padrão	
  para	
  o	
  desenvolvimento	
  de	
  aplicações	
  para	
  o	
  Mac	
  OS	
  e	
  hoje	
  
também	
  para	
  o	
  iOS,	
  ambos	
  sistemas	
  operacionais	
  desenvolvidos	
  pela	
  Apple.	
  A	
  
linguagem	
  é	
  derivada	
  diretamente	
  do	
  C,	
  com	
  algumas	
  características	
  de	
  
Smalltalk,	
  como	
  o	
  uso	
  de	
  parâmetros	
  dentro	
  do	
  nome	
  do	
  método	
  em	
  vez	
  de	
  em	
  
uma	
  seção	
  de	
  parâmetros	
  no	
  mesmo.	
  
Vamos	
  fazer	
  agora	
  dar	
  os	
  nossos	
  primeiros	
  passos	
  com	
  o	
  XCode,	
  criando	
  um	
  
projeto.	
  Abra	
  o	
  XCode,	
  essa	
  deve	
  ser	
  a	
  primeira	
  janela	
  que	
  você	
  vai	
  ver:	
  
Imagem	
  1	
  –	
  Seleção	
  de	
  projetos	
  no	
  XCode	
  
	
  
Nessa	
  página,	
  selecione	
  “Create	
  a	
  new	
  Xcode	
  project”,	
  aqui	
  está	
  a	
  próxima	
  janela	
  
que	
  você	
  vai	
  ver:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   4	
  
Imagem	
  2	
  –	
  Criando	
  o	
  projeto	
  no	
  Xcode	
  
	
  
Nesse	
  primeiro	
  momento,	
  vamos	
  iniciar	
  com	
  uma	
  aplicação	
  para	
  MacOS,	
  pra	
  
entender	
  o	
  funcionamento	
  da	
  linguagem	
  e	
  nos	
  acostumarmos	
  com	
  o	
  Xcode	
  como	
  
ferramenta.	
  Após	
  selecionar	
  “Mac	
  OS	
  X”	
  -­‐>	
  “Application”	
  -­‐>	
  “Command	
  Line	
  
Tool”,	
  além	
  de	
  selecionar	
  “Foundation”	
  no	
  campo	
  de	
  seleção.	
  Dê	
  o	
  nome	
  	
  
“AprendendoObjectivec”	
  ao	
  projeto.	
  
Com	
  o	
  projeto	
  criado,	
  você	
  deve	
  ver	
  uma	
  janela	
  como	
  essa	
  agora:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   5	
  
Imagem	
  3	
  –	
  Visualização	
  inicial	
  do	
  projeto	
  
	
  
Um	
  fator	
  interessante	
  ao	
  se	
  iniciar	
  o	
  desenvolvimento	
  usando	
  Xcode	
  é	
  que	
  
mesmo	
  se	
  parecendo	
  com	
  pastas,	
  “Source”,	
  “Documentation”,	
  “External	
  
frameworks	
  and	
  libraries”	
  e	
  “Products”	
  não	
  são	
  pastas,	
  mas	
  “agrupamentos”	
  de	
  
conteúdo.	
  Se	
  você	
  for	
  até	
  a	
  pasta	
  que	
  está	
  o	
  projeto,	
  vai	
  perceber	
  que	
  não	
  
existem	
  diretórios	
  equivalentes	
  a	
  eles,	
  isso	
  acontece	
  porque	
  o	
  Xcode	
  organiza	
  os	
  
arquivos	
  apenas	
  logicamente	
  e	
  não	
  fisicamente	
  dentro	
  do	
  projeto.	
  
Com	
  o	
  nosso	
  projeto	
  criado,	
  vamos	
  criar	
  um	
  target	
  para	
  os	
  testes	
  unitários	
  que	
  
vamos	
  escrever	
  durante	
  o	
  exemplo.	
  Pra	
  fazer	
  isso,	
  clique	
  com	
  o	
  botão	
  direito	
  ou	
  
“Control	
  	
  +	
  Click”	
  no	
  marcador	
  “Targets”,	
  siga	
  para	
  “Add”,	
  depois	
  “New	
  Target”.	
  
Você	
  deve	
  ver	
  a	
  tela	
  abaixo:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   6	
  
Imagem	
  4	
  –	
  Criando	
  o	
  target	
  que	
  vai	
  rodar	
  os	
  nossos	
  testes	
  
	
  
Ao	
  partir	
  pra	
  próxima	
  tela	
  você	
  vai	
  definir	
  o	
  nome	
  do	
  target,	
  coloque	
  o	
  nome	
  
Test.	
  Assim	
  que	
  o	
  target	
  for	
  criado,	
  ele	
  vai	
  abrir	
  a	
  janela	
  de	
  opções	
  do	
  mesmo,	
  
nela,	
  selecione	
  a	
  aba	
  “General”,	
  clique	
  no	
  botão	
  “+”,	
  você	
  deve	
  ver	
  então	
  uma	
  
janela	
  como	
  a	
  imagem	
  logo	
  abaixo,	
  selecione	
  “AprendendoObjectivec”	
  e	
  clique	
  
em	
  “Add	
  Target”.	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   7	
  
Imagem	
  5	
  –	
  Adicionando	
  o	
  executável	
  da	
  aplicação	
  como	
  dependência	
  ao	
  target	
  
Test	
  
	
  
Estamos	
  agora	
  finalmente	
  prontos	
  pra	
  começar	
  a	
  escrever	
  o	
  código	
  do	
  projeto.	
  
Para	
  entender	
  as	
  construções	
  básicas	
  da	
  linguagem,	
  vamos	
  criar	
  uma	
  classe	
  
Conta	
  que	
  guarde	
  os	
  dados	
  de	
  agência,	
  número	
  de	
  conta,	
  banco	
  e	
  saldo.	
  Além	
  
disso	
  a	
  classe	
  também	
  vai	
  conter	
  os	
  métodos	
  para	
  sacar,	
  depositar	
  e	
  transferir	
  
dinheiro	
  entre	
  contas.	
  
Selecione	
  o	
  grupo	
  “Source”	
  e	
  abra	
  o	
  menu	
  contextual.	
  Vá	
  em	
  “Add”	
  -­‐>	
  “New	
  File”.	
  
Selecione	
  “Cocoa	
  Class”	
  e	
  depois	
  “Objective-­‐C	
  class”,	
  como	
  na	
  imagem	
  abaixo:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   8	
  
Imagem	
  6	
  –	
  Criando	
  a	
  nossa	
  primeira	
  classe	
  em	
  Objective-­‐C	
  
	
  
Na	
  próxima	
  janela,	
  coloque	
  o	
  nome	
  da	
  classe	
  como	
  sendo	
  “Conta.m”	
  e	
  marque	
  o	
  
checkbox	
  “Also	
  create	
  ‘Conta.h’”:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   9	
  
Imagem	
  7	
  –	
  Criando	
  a	
  nossa	
  primeira	
  classe	
  em	
  Objective-­‐C	
  
	
  
Com	
  a	
  classe	
  criada,	
  você	
  deve	
  ver	
  os	
  arquivos	
  no	
  Xcode	
  como	
  na	
  imagem	
  abaixo:	
  
Imagem	
  8	
  –	
  visualização	
  do	
  navegador	
  de	
  arquivos	
  com	
  a	
  classe	
  Conta	
  criada.	
  
	
  
Olhando	
  pra	
  essa	
  imagem	
  podemos	
  ver	
  que	
  existe	
  um	
  arquivo	
  “Conta.m”	
  e	
  um	
  
arquivo	
  “Conta.h”,	
  vejamos	
  o	
  que	
  há	
  de	
  código	
  em	
  cada	
  um	
  desses	
  arquivos:	
  
Listagem	
  1	
  –	
  Conta.h	
  
#import <Cocoa/Cocoa.h>
@interface Conta : NSObject {
}
@end
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   10	
  
Se	
  você	
  nunca	
  programou	
  em	
  C	
  na	
  vida,	
  deve	
  estar	
  se	
  perguntando	
  porque	
  temos	
  
dois	
  arquivos	
  para	
  uma	
  única	
  classe,	
  um	
  “.h”	
  e	
  outro	
  “.m”.	
  O	
  arquivo	
  “.h”,	
  
funciona	
  como	
  “cabeçalho”	
  (daí	
  o	
  “.h”,	
  de	
  “header”),	
  nele	
  você	
  define	
  a	
  interface	
  
pública	
  da	
  classe,	
  como	
  os	
  atributos	
  que	
  ela	
  tem	
  e	
  os	
  métodos	
  que	
  ela	
  
implementa	
  (e	
  que	
  devem	
  ficar	
  visíveis	
  para	
  terceiros).	
  
Em	
  Objective-­‐C,	
  diferentemente	
  de	
  Java	
  e	
  outras	
  linguagens,	
  não	
  existem	
  
modificadores	
  de	
  nível	
  de	
  visibilidade	
  para	
  as	
  classes	
  ou	
  os	
  seus	
  membros	
  (como	
  
métodos	
  e	
  atributos),	
  tudo	
  é	
  “visível”,	
  mas	
  apenas	
  o	
  que	
  estiver	
  definido	
  no	
  
arquivo	
  “.h”	
  fica	
  realmente	
  disponível	
  para	
  outros	
  objetos	
  que	
  queiram	
  usar	
  a	
  
sua	
  classe.	
  
Olhando	
  agora	
  diretamente	
  para	
  o	
  código	
  fonte,	
  vemos	
  o	
  “#import	
  
<Cocoa/Cocoa.h>”,	
  isso	
  quer	
  dizer	
  que	
  a	
  nossa	
  classe	
  está	
  declarando	
  que	
  vai	
  
utilizar	
  funcionalidades	
  do	
  framework	
  “Cocoa”	
  (na	
  verdade	
  nós	
  só	
  precisamos	
  
do	
  framework	
  “Foundation”,	
  mas	
  vamos	
  deixar	
  assim	
  por	
  enquanto).	
  Logo	
  após	
  
isso	
  vemos	
  o	
  seguinte	
  código:	
  
@interface	
  Conta	
  :	
  NSObject	
  
Sempre	
  que	
  você	
  vir	
  um	
  caractere	
  “@”	
  (arroba)	
  em	
  código	
  escrito	
  em	
  Objective-­‐
C,	
  quer	
  dizer	
  que	
  o	
  que	
  vem	
  logo	
  após	
  ele	
  é	
  uma	
  extensão	
  da	
  linguagem	
  ao	
  C.	
  
Opa,	
  peraí,	
  como	
  assim	
  uma	
  “extensão	
  a	
  linguagem	
  C”?	
  
Objective-­‐C,	
  assim	
  como	
  C++,	
  existe	
  como	
  uma	
  extensão	
  a	
  linguagem	
  C.	
  Você	
  
pode	
  escrever	
  código	
  C	
  dentro	
  de	
  programas	
  escritos	
  em	
  Objective-­‐C	
  e	
  o	
  seu	
  
código	
  (teoricamente)	
  vai	
  compilar	
  e	
  funcionar	
  normalmente.	
  Os	
  designers	
  da	
  
linguagem	
  resolveram	
  então	
  definir	
  uma	
  forma	
  de	
  deixar	
  claro	
  o	
  que	
  não	
  é	
  “C	
  
puro”	
  na	
  linguagem	
  usando	
  o	
  caracter	
  “@”.	
  Então	
  sempre	
  que	
  você	
  vir	
  o	
  “@”	
  já	
  
sabe	
  que	
  isso	
  é	
  uma	
  extensão	
  do	
  Objective-­‐C	
  para	
  adicionar	
  novos	
  
comportamentos	
  ao	
  nosso	
  querido	
  e	
  amado	
  C.	
  
A	
  extensão	
  @interface	
  diz	
  que	
  estamos	
  definindo	
  uma	
  nova	
  classe	
  na	
  linguagem	
  
e	
  o	
  que	
  segue	
  essa	
  declaração	
  é	
  o	
  nome	
  da	
  classe,	
  no	
  nosso	
  caso	
  “Conta”.	
  Logo	
  
após	
  a	
  declaração	
  do	
  nome	
  da	
  classe	
  o	
  “:	
  NSObject”	
  diz	
  que	
  a	
  nossa	
  classe	
  “Conta”	
  
herda	
  de	
  “NSObject”.	
  Diferentemente	
  de	
  outras	
  linguagens	
  onde	
  existe	
  uma	
  única	
  
classe	
  raiz	
  e	
  mãe	
  de	
  todos	
  os	
  objetos	
  (pense	
  no	
  Object	
  de	
  Java,	
  Ruby,	
  C#	
  e	
  tantas	
  
outras),	
  em	
  Objective-­‐C	
  você	
  mesmo	
  pode	
  definir	
  uma	
  classe	
  raiz,	
  mas	
  
normalmente	
  você	
  vai	
  herdar	
  de	
  “NSObject”	
  que	
  é	
  a	
  classe	
  raiz	
  do	
  framework	
  
base	
  de	
  Objective-­‐C	
  utilizado	
  no	
  desenvolvimento	
  de	
  aplicações	
  para	
  o	
  Mac	
  OS	
  e	
  
iOS.	
  Obviamente,	
  se	
  você	
  não	
  disser	
  de	
  qual	
  classe	
  você	
  herda,	
  a	
  sua	
  classe	
  se	
  
torna	
  automaticamente	
  uma	
  classe	
  raiz,	
  então	
  lembre-­‐se	
  sempre	
  de	
  definir	
  a	
  
superclasse	
  da	
  sua	
  classe	
  ou	
  simplesmente	
  coloque	
  que	
  ela	
  herda	
  de	
  “NSObject”.	
  
O	
  par	
  de	
  chaves	
  “{}”	
  que	
  vem	
  logo	
  após	
  a	
  declaração	
  da	
  classe	
  é	
  o	
  lugar	
  onde	
  
você	
  define	
  as	
  variáveis	
  de	
  instância	
  da	
  sua	
  classe	
  e	
  somente	
  elas	
  (não,	
  não	
  é	
  
aqui	
  que	
  você	
  coloca	
  os	
  métodos).	
  Todas	
  as	
  variáveis	
  de	
  instância	
  precisam	
  estar	
  
definidas	
  aqui	
  no	
  arquivo	
  “.h”,	
  mesmo	
  aquelas	
  que	
  você	
  queira	
  deixar	
  como	
  
“privadas”.	
  
Após	
  o	
  par	
  de	
  chaves	
  vem	
  o	
  corpo	
  da	
  classe,	
  que	
  é	
  o	
  lugar	
  onde	
  você	
  define	
  os	
  
métodos	
  que	
  essa	
  classe	
  implementa	
  (mas	
  você	
  não	
  os	
  implementa	
  aqui,	
  você	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   11	
  
apenas	
  define	
  quais	
  são	
  eles).	
  Não	
  definir	
  um	
  método	
  aqui	
  normalmente	
  faz	
  com	
  
que	
  não	
  seja	
  possível	
  pra	
  que	
  alguém	
  o	
  invoque,	
  é	
  uma	
  das	
  formas	
  de	
  se	
  criar	
  
métodos	
  “privados”	
  em	
  Objective-­‐C,	
  já	
  que	
  não	
  existe	
  esse	
  conceito	
  dentro	
  da	
  
linguagem	
  em	
  si.	
  
Listagem	
  2	
  –	
  Conta.m	
  
#import "Conta.h"
@implementation Conta
@end
	
  No	
  arquivo	
  “.m”	
  você	
  encontra	
  agora	
  o	
  código	
  real	
  da	
  classe	
  (mesmo	
  que	
  não	
  
tenhamos	
  colocado	
  nada	
  ainda	
  nele.	
  Enquanto	
  que	
  no	
  arquivo	
  “.h”	
  nós	
  havíamos	
  
definido	
  a	
  @interface	
  do	
  código,	
  agora	
  estamos	
  definindo	
  a	
  @implementation.	
  
Veja	
  que	
  aqui	
  não	
  é	
  mais	
  necessário	
  definir	
  de	
  qual	
  classe	
  a	
  nossa	
  classe	
  herda,	
  a	
  
definição	
  fica	
  apenas	
  na	
  interface.	
  	
  
Veja	
  que	
  o	
  código	
  também	
  faz	
  um	
  “#import”	
  para	
  o	
  arquivo	
  “.h”,	
  isso	
  é	
  para	
  que	
  o	
  
arquivo	
  de	
  implementação	
  possa	
  ver	
  as	
  informações	
  definidas	
  na	
  interface,	
  como	
  
variáveis	
  de	
  instância	
  e	
  também	
  receber	
  automaticamente	
  as	
  dependências	
  que	
  
já	
  foram	
  importadas	
  no	
  mesmo.	
  Em	
  C	
  você	
  faria	
  o	
  mesmo	
  com	
  #include,	
  mas	
  o	
  
#import	
  vai	
  um	
  pouco	
  mais	
  longe	
  e	
  evita	
  que	
  o	
  mesmo	
  arquivo	
  seja	
  “incluído”	
  
duas	
  vezes,	
  um	
  problema	
  bem	
  comum	
  pra	
  quem	
  trabalha	
  com	
  C.	
  
Vamos	
  agora	
  começar	
  a	
  realmente	
  escrever	
  código:	
  
Listagem	
  3	
  –	
  Conta.h	
  
#import <Cocoa/Cocoa.h>
@interface Conta : NSObject {
float saldo;
}
- (BOOL) depositar:(float)valor;
- (float) saldo;
@end
Agora	
  a	
  nossa	
  classe	
  conta	
  tem	
  uma	
  variável	
  de	
  instância	
  definida	
  (do	
  tipo	
  
“float”),	
  declaramos	
  a	
  existência	
  do	
  método	
  depositar	
  que	
  recebe	
  um	
  parâmetro	
  
do	
  tipo	
  float	
  	
  e	
  retorna	
  um	
  BOOL,	
  o	
  boolean	
  da	
  linguagem.	
  Também	
  declaramos	
  o	
  
método	
  “saldo”	
  que	
  vai	
  ser	
  a	
  forma	
  de	
  acessar	
  a	
  variável	
  de	
  instância	
  “saldo”.	
  É	
  
possível	
  acessar	
  uma	
  variável	
  de	
  instância	
  de	
  uma	
  classe	
  em	
  Objective-­‐C	
  
diretamente	
  de	
  “fora”	
  da	
  classe,	
  mas	
  o	
  melhor	
  é	
  fazer	
  o	
  acesso	
  sempre	
  via	
  
métodos	
  (ou	
  as	
  propriedades	
  que	
  veremos	
  mais	
  a	
  frente).	
  
O	
  sinal	
  de	
  “-­‐“	
  (subtração)	
  antes	
  da	
  definição	
  do	
  método	
  avisa	
  que	
  esse	
  é	
  um	
  
método	
  de	
  instância	
  (métodos	
  de	
  classe	
  são	
  definidos	
  com	
  um	
  sinal	
  de	
  adição,	
  o	
  
“+”).	
  O	
  tipo	
  de	
  retorno	
  e	
  o	
  tipo	
  dos	
  parâmetros	
  recebidos	
  ficam	
  sempre	
  entre	
  
parênteses.	
  	
  
Um	
  detalhe	
  importante	
  na	
  declaração	
  de	
  métodos	
  em	
  Objective-­‐C	
  é	
  que	
  o	
  
parâmetro	
  fica	
  “dentro”	
  do	
  nome	
  do	
  método	
  e	
  não	
  após	
  a	
  definição	
  do	
  nome,	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   12	
  
como	
  em	
  Java	
  ou	
  Ruby.	
  Como	
  o	
  método	
  depositar	
  recebe	
  um	
  parâmetro	
  é	
  
necessário	
  colocar	
  os	
  “:”	
  para	
  separar	
  o	
  nome	
  do	
  parâmetro	
  que	
  está	
  sendo	
  
passado,	
  depois	
  vamos	
  entender	
  um	
  pouco	
  mais	
  como	
  se	
  nomeiam	
  métodos	
  em	
  
Objective-­‐C.	
  
Vejamos	
  então	
  como	
  vai	
  ficar	
  o	
  nosso	
  arquivo	
  “.m”:	
  
Listagem	
  4	
  –	
  Conta.m	
  
#import "Conta.h"
@implementation Conta
- (BOOL) depositar: (float) valor {
if ( valor > 0 ) {
saldo += valor;
return YES;
} else {
return NO;
}
}
- (float) saldo {
return saldo;
}
@end
Olhando	
  pro	
  código	
  fonte	
  você	
  já	
  deve	
  ter	
  entendido	
  exatamente	
  o	
  que	
  ele	
  faz,	
  se	
  
o	
  valor	
  passado	
  como	
  parâmetro	
  for	
  maior	
  do	
  que	
  zero,	
  ele	
  vai	
  somar	
  com	
  o	
  
valor	
  atual	
  da	
  variável	
  de	
  instância	
  “saldo”	
  e	
  retornar	
  YES,	
  que	
  é	
  um	
  atalho	
  para	
  o	
  
valor	
  BOOL	
  que	
  representa	
  verdadeiro,	
  se	
  o	
  valor	
  passado	
  como	
  parâmetro	
  for	
  
menor	
  ou	
  igual	
  a	
  zero	
  ele	
  simplesmente	
  retorna	
  NO.	
  
Assim	
  como	
  em	
  C,	
  blocos	
  de	
  código	
  em	
  Objective-­‐C	
  ficam	
  sempre	
  dentro	
  de	
  pares	
  
de	
  chaves	
  (“{}”)	
  e	
  todas	
  as	
  estruturas	
  de	
  controle	
  que	
  você	
  conhece	
  do	
  C	
  (ou	
  Java	
  
e	
  C#)	
  existem	
  exatamente	
  da	
  mesma	
  forma	
  em	
  Objective-­‐C.	
  
A	
  implementação	
  do	
  método	
  “saldo”	
  é	
  ainda	
  mais	
  trivial,	
  ela	
  simplesmente	
  
retorna	
  o	
  valor	
  da	
  variável	
  de	
  instância	
  diretamente.	
  
Criando	
  o	
  nosso	
  primeiro	
  teste	
  unitário	
  
Com	
  a	
  nossa	
  classe	
  implementada,	
  agora	
  é	
  a	
  hora	
  de	
  escrever	
  um	
  teste	
  para	
  esse	
  
primeiro	
  método	
  implementado.	
  A	
  primeira	
  coisa	
  a	
  se	
  fazer	
  é	
  criar	
  um	
  novo	
  
grupo	
  dentro	
  do	
  projeto	
  pra	
  manter	
  as	
  classes	
  de	
  teste,	
  assim	
  podemos	
  
facilmente	
  separar	
  as	
  classes	
  dos	
  seus	
  testes	
  na	
  hora	
  de	
  gerar	
  a	
  aplicação	
  final,	
  já	
  
que	
  ela	
  não	
  precisa	
  levar	
  os	
  testes	
  consigo.	
  Clique	
  com	
  o	
  botão	
  direito	
  em	
  
“AprendendoObjectivec”,	
  como	
  na	
  imagem	
  abaixo:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   13	
  
Imagem	
  9	
  –	
  Criando	
  o	
  grupo	
  “Test”	
  
	
  
Com	
  o	
  grupo	
  criado,	
  clique	
  com	
  o	
  botão	
  direito	
  em	
  “Test”,	
  selecione	
  “Add”	
  e	
  
“New	
  File”.	
  Você	
  vai	
  criar	
  uma	
  classe	
  de	
  teste	
  padrão	
  do	
  Cocoa,	
  como	
  na	
  imagem	
  
abaixo:	
  
Imagem	
  10	
  –	
  Criando	
  a	
  classe	
  de	
  testes	
  
	
  
Dê	
  o	
  nome	
  “ContaTest”	
  a	
  classe	
  e	
  selecione	
  o	
  Target	
  “Test”	
  apenas,	
  desmarcando	
  
o	
  primeiro	
  Target	
  que	
  aparece,	
  como	
  na	
  imagem	
  abaixo:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   14	
  
Imagem	
  11	
  –	
  Selecionando	
  os	
  targets	
  da	
  classe	
  de	
  testes	
  
	
  
No	
  caso	
  dos	
  testes,	
  você	
  normalmente	
  não	
  precisa	
  definir	
  nada	
  no	
  arquivo	
  “.h”,	
  já	
  
que	
  os	
  métodos	
  são	
  chamados	
  automaticamente,	
  então	
  vamos	
  nos	
  focar	
  apenas	
  
no	
  arquivo	
  “.m”,	
  que	
  é	
  onde	
  nós	
  vamos	
  realmente	
  estar	
  trabalhando.	
  	
  
Implementando	
  o	
  nosso	
  primeiro	
  teste	
  
Listagem	
  5	
  –	
  ContaTest.m	
  
#import "ContaTest.h"
#import "Conta.h"
@implementation ContaTest
- (void) testDepositarComSucesso {
Conta * conta = [[Conta alloc] init];
[conta depositar:200];
STAssertTrue( [conta saldo] == 300, @"O saldo deve ser de
300 para que o teste falhe" );
}
@end
Assim	
  como	
  em	
  outros	
  frameworks	
  de	
  teste,	
  o	
  método	
  que	
  define	
  a	
  
implementação	
  do	
  teste	
  precisa	
  ter	
  o	
  seu	
  nome	
  iniciando	
  com	
  “test”	
  e	
  não	
  
retornar	
  nada	
  (por	
  isso	
  o	
  void).	
  Na	
  primeira	
  linha	
  do	
  teste	
  já	
  temos	
  vários	
  
detalhes	
  da	
  linguagem	
  pra	
  entender.	
  	
  
A	
  primeira	
  coisa	
  a	
  ser	
  percebida	
  é	
  que	
  a	
  declaração	
  da	
  variável	
  contém	
  um	
  “*”,	
  se	
  
você	
  vem	
  do	
  C,	
  sabe	
  que	
  isso	
  quer	
  dizer	
  que	
  essa	
  variável	
  é	
  na	
  verdade	
  uma	
  
referencia	
  (ou	
  ponteiro)	
  pra	
  um	
  objeto	
  que	
  está	
  em	
  memória.	
  Sempre	
  que	
  você	
  
define	
  uma	
  referencia	
  pra	
  uma	
  variável	
  em	
  Objective-­‐C	
  é	
  necessário	
  colocar	
  o	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   15	
  
“*”,	
  se	
  você	
  não	
  o	
  fizer	
  vai	
  receber	
  warnings	
  do	
  compilador	
  e	
  o	
  seu	
  programa	
  não	
  
vai	
  funcionar	
  corretamente.	
  
Ainda	
  nessa	
  linha	
  temos	
  o	
  idioma	
  de	
  inicialização	
  de	
  objetos.	
  O	
  que	
  em	
  outras	
  
linguagens	
  de	
  programação	
  OO	
  seria	
  feito	
  através	
  de	
  um	
  construtor,	
  em	
  
Objective-­‐C	
  se	
  faz	
  através	
  das	
  chamadas	
  a	
  “alloc”,	
  um	
  método	
  de	
  classe	
  que	
  
organiza	
  uma	
  nova	
  instância	
  do	
  objeto	
  em	
  memória	
  e	
  retorna	
  o	
  objeto	
  pronto	
  
pra	
  uso,	
  e	
  “init”,	
  que	
  executa	
  finalmente	
  a	
  inicialização	
  do	
  objeto.	
  É	
  possível	
  usar	
  
também	
  o	
  método	
  de	
  classe	
  “new”	
  em	
  vez	
  do	
  “par”	
  alloc/init	
  para	
  se	
  criar	
  um	
  
objeto,	
  mas	
  é	
  preferível	
  usar	
  alloc/init,	
  especialmente	
  se	
  você	
  pretende	
  ter	
  várias	
  
formas	
  de	
  inicializar	
  o	
  seu	
  objeto.	
  
Ótimo,	
  você	
  diz,	
  mas	
  o	
  que	
  diabos	
  são	
  aqueles	
  pares	
  de	
  colchetes	
  (“[]”)?	
  
Seguindo	
  a	
  tradição	
  de	
  Smalltalk,	
  em	
  Objective-­‐C	
  a	
  ideia	
  não	
  é	
  que	
  você	
  está	
  
chamando	
  um	
  método	
  em	
  um	
  objeto,	
  mas	
  sim	
  enviando	
  uma	
  mensagem	
  a	
  ele.	
  
Inicialmente,	
  a	
  sintaxe	
  pode	
  realmente	
  parecer	
  um	
  pouco	
  estranha,	
  mas	
  no	
  fim	
  
das	
  contas	
  ela	
  é	
  bem	
  simples:	
  
[	
  objetoDestino	
  mensagem	
  ]	
  
Do	
  lado	
  esquerdo,	
  você	
  sempre	
  tem	
  o	
  objeto	
  para	
  o	
  qual	
  você	
  quer	
  enviar	
  a	
  
mensagem,	
  do	
  lado	
  direito	
  você	
  tem	
  a	
  mensagem	
  que	
  está	
  sendo	
  enviada	
  (o	
  
método	
  que	
  está	
  sendo	
  chamado),	
  tudo	
  isso	
  dentro	
  de	
  colchetes.	
  No	
  nosso	
  caso,	
  
onde	
  fazemos	
  “[[Conta alloc] init]”,	
  estamos	
  enviando	
  a	
  mensagem	
  “alloc”	
  
para	
  o	
  objeto	
  que	
  representa	
  a	
  classe	
  “Conta”	
  e	
  no	
  valor	
  que	
  é	
  retornado	
  por	
  esse	
  
método	
  (um	
  objeto	
  Conta)	
  fazemos	
  a	
  chamada	
  do	
  método	
  “init”.	
  O	
  idioma	
  
alloc/init	
  é	
  comum	
  e	
  pervasivo	
  em	
  toda	
  a	
  linguagem	
  e	
  exemplos	
  de	
  código	
  que	
  
você	
  vai	
  encontrar,	
  mas	
  evite	
  fazer	
  chamadas	
  de	
  método	
  dentro	
  de	
  chamadas	
  de	
  
método	
  no	
  seu	
  código,	
  a	
  não	
  ser	
  que	
  seja	
  um	
  caso	
  muito	
  simples	
  como	
  esse	
  que	
  
nós	
  estamos	
  vendo	
  aqui.	
  
Na	
  segunda	
  linha	
  do	
  teste	
  vemos	
  o	
  seguinte:	
  
[conta depositar:200];
Nós	
  enviamos	
  a	
  mensagem	
  “depositar”	
  para	
  o	
  objeto	
  representado	
  pela	
  variável	
  
“conta”	
  com	
  o	
  parâmetro	
  200.	
  Os	
  “:”	
  que	
  nós	
  usamos	
  na	
  definição	
  do	
  método	
  
“depositar”	
  fazem	
  realmente	
  parte	
  do	
  nome	
  do	
  método,	
  sendo	
  obrigatório	
  a	
  sua	
  
adição	
  a	
  chamada	
  (os	
  métodos	
  que	
  não	
  adicionam	
  “:”	
  são	
  os	
  que	
  não	
  recebem	
  
parâmetros).	
  
No	
  fim	
  temos	
  o	
  código	
  que	
  faz	
  a	
  asserção	
  do	
  teste:	
  
STAssertTrue( [conta saldo] == 300, @"O saldo deve ser de
300 para que o teste falhe" );
Comparamos	
  então	
  o	
  valor	
  do	
  saldo	
  com	
  300	
  exatamente	
  porque	
  queremos,	
  
nesse	
  primeiro	
  momento,	
  ver	
  o	
  teste	
  falhar.	
  STAssertTrue	
  não	
  é	
  um	
  método,	
  mas	
  
uma	
  função	
  comum	
  que	
  você	
  definiria	
  como	
  uma	
  função	
  em	
  C,	
  ela	
  faz	
  parte	
  do	
  
framework	
  de	
  testes	
  unitários	
  que	
  vem	
  por	
  padrão	
  dentro	
  do	
  Cocoa.	
  
Agora	
  um	
  detalhe	
  importante	
  que	
  pode	
  passar	
  desapercebido	
  é	
  a	
  definição	
  do	
  
texto	
  usado	
  como	
  mensagem	
  para	
  esse	
  teste,	
  em	
  vez	
  de	
  ser	
  somente	
  um	
  conjunto	
  
de	
  caracteres	
  entre	
  aspas,	
  há	
  um	
  “@”	
  antes	
  das	
  aspas.	
  Isso	
  quer	
  dizer	
  que	
  você	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   16	
  
não	
  está	
  usando	
  uma	
  string	
  comum	
  do	
  C,	
  que	
  é	
  um	
  array	
  de	
  caracteres,	
  e	
  sim	
  um	
  
objeto	
  do	
  tipo	
  NSString	
  que	
  adiciona	
  várias	
  funcionalidades	
  as	
  strings	
  comuns	
  do	
  
C.	
  A	
  maior	
  parte	
  do	
  código	
  em	
  Objective-­‐C	
  que	
  lida	
  com	
  Strings	
  vai	
  esperar	
  que	
  
você	
  envie	
  objetos	
  do	
  tipo	
  NSString,	
  então	
  é	
  bom	
  se	
  acostumar	
  a	
  escrever	
  
primeiro	
  a	
  “@”	
  antes	
  de	
  declarar	
  um	
  string	
  no	
  seu	
  código.	
  
Voltemos	
  agora	
  para	
  o	
  Xcode,	
  onde	
  você	
  vai	
  mudar	
  o	
  Target	
  padrão	
  para	
  Test,	
  
veja	
  como	
  fazer	
  isso	
  na	
  imagem	
  abaixo:	
  
Imagem	
  12	
  –	
  Alterando	
  o	
  Target	
  padrão	
  para	
  Test	
  
	
  
Agora	
  estamos	
  entrando	
  no	
  modo	
  de	
  testes	
  do	
  Xcode	
  vamos	
  poder	
  começar	
  a	
  
executar	
  os	
  testes,	
  mas	
  antes	
  de	
  fazer	
  isso	
  precisamos	
  dizer	
  para	
  o	
  Target	
  “Test”	
  
onde	
  ele	
  vai	
  achar	
  a	
  classe	
  Conta,	
  pois	
  ela	
  não	
  foi	
  adicionada	
  a	
  ele.	
  Pra	
  fazer	
  isso,	
  
você	
  deve	
  selecionar	
  o	
  arquivo	
  “Conta.m”	
  e	
  arrastá-­‐lo	
  para	
  dentro	
  da	
  pasta	
  
“Compile	
  Sources”	
  do	
  Target	
  “Test”,	
  como	
  na	
  imagem	
  abaixo:	
  
Imagem	
  13	
  –	
  Drag	
  e	
  drop	
  do	
  arquivo	
  “Conta.m”	
  em	
  Test	
  
	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   17	
  
Com	
  isso	
  feito,	
  podemos	
  finalmente	
  executar	
  o	
  build	
  do	
  projeto,	
  pra	
  fazer	
  isso	
  
digite	
  “Command	
  +	
  B”.	
  Após	
  alguns	
  instantes	
  o	
  Xcode	
  deve	
  terminar	
  de	
  fazer	
  o	
  
build	
  e	
  você	
  deve	
  ver	
  um	
  aviso	
  no	
  canto	
  inferior	
  direito	
  da	
  ferramenta	
  indicando	
  
que	
  existem	
  dois	
  erros:	
  
Imagem	
  14	
  –	
  Indicação	
  de	
  erros	
  de	
  build	
  do	
  Xcode	
  
	
  
Ao	
  clicar	
  nos	
  erros	
  você	
  deve	
  ver	
  a	
  seguinte	
  tela:	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   18	
  
Imagem	
  15	
  –	
  tela	
  de	
  erros	
  no	
  build	
  do	
  Xcode	
  
	
  
Como	
  você	
  pode	
  perceber,	
  o	
  erro	
  na	
  verdade	
  não	
  é	
  exatamente	
  no	
  build,	
  mas	
  sim	
  
no	
  nosso	
  teste	
  unitário	
  que	
  falhou,	
  já	
  que	
  o	
  valor	
  da	
  variável	
  não	
  é	
  300	
  e	
  sim	
  200.	
  
Para	
  ver	
  essa	
  tela	
  sem	
  ter	
  que	
  usar	
  o	
  mouse	
  pra	
  clicar	
  no	
  erro	
  basta	
  fazer	
  “Shift	
  +	
  
Command	
  +	
  B”.	
  Agora	
  que	
  você	
  já	
  viu	
  a	
  tela,	
  troque	
  o	
  300	
  por	
  200	
  e	
  execute	
  o	
  
build	
  mais	
  uma	
  vez	
  com	
  “Command	
  +	
  B”,	
  o	
  seu	
  build	
  deve	
  executar	
  sem	
  erros,	
  
agora	
  que	
  o	
  teste	
  já	
  está	
  implementado	
  corretamente.	
  
Vamos	
  agora	
  definir	
  os	
  métodos	
  sacar	
  e	
  transferir	
  na	
  classe	
  conta:	
  
Listagem	
  6	
  –	
  Conta.h	
  
#import <Cocoa/Cocoa.h>
@interface Conta : NSObject {
float saldo;
}
- (BOOL) depositar: (float) valor;
- (BOOL) sacar: (float) valor;
- (BOOL) transferir: (float) valor para: (Conta *) destino;
- (float) saldo;
@end
Estamos	
  quase	
  chegando	
  lá,	
  o	
  método	
  sacar	
  tem	
  a	
  definição	
  igual	
  a	
  depositar,	
  
mas	
  o	
  método	
  “transferir:para:”	
  (veja	
  só	
  como	
  ele	
  se	
  chama)	
  deve	
  estar	
  dando	
  
um	
  nó	
  no	
  seu	
  cérebro	
  nesse	
  momento.	
  Vejamos:	
  
- (BOOL) transferir: (float) valor para: (Conta *) destino;
Em	
  Objective-­‐C,	
  quando	
  você	
  tem	
  um	
  método	
  que	
  recebe	
  vários	
  parâmetros,	
  
você	
  precisa	
  “dividir”	
  o	
  nome	
  do	
  método	
  em	
  pedaços	
  para	
  receber	
  os	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   19	
  
parâmetros.	
  Então	
  em	
  vez	
  de	
  simplesmente	
  fazer	
  um	
  “transferir(	
  double	
  valor,	
  
Conta	
  destino	
  )”,	
  como	
  você	
  faria	
  em	
  Java	
  ou	
  C#,	
  você	
  quebra	
  o	
  nome	
  do	
  método	
  
e	
  transformar	
  ele	
  em	
  “transferir:	
  valor	
  para:	
  destino”.	
  	
  
Inicialmente	
  a	
  sintaxe	
  parece	
  estranha,	
  mas	
  a	
  própria	
  leitura	
  da	
  chamada	
  do	
  
método	
  fica	
  mais	
  simples	
  e	
  se	
  você	
  tiver	
  um	
  método	
  que	
  recebe	
  vários	
  
parâmetros	
  ele	
  com	
  certeza	
  vai	
  ficar	
  bem	
  mais	
  legível,	
  já	
  que	
  cada	
  parâmetro	
  vai	
  
ter	
  o	
  seu	
  identificador	
  antes.	
  	
  
Vejamos	
  agora	
  como	
  fica	
  a	
  implementação	
  desses	
  dois	
  métodos:	
  
Listagem	
  7	
  –	
  Conta.m	
  
#import "Conta.h"
@implementation Conta
- (BOOL) depositar: (float) valor {
if ( valor > 0 ) {
saldo += valor;
return YES;
} else {
return NO;
}
}
- (BOOL) sacar:(float)valor {
if ( valor > 0 && valor <= saldo) {
saldo -= valor;
return YES;
} else {
return NO:
}
}
- (BOOL) transferir:(float) valor para:(Conta *) destino {
if ( [self sacar: valor]
&& [ destino depositar: valor ] ){
return YES;
} else {
return NO;
}
}
- (float) saldo {
return saldo;
}
@end
A	
  essa	
  altura	
  do	
  campeonato,	
  você	
  já	
  sabe	
  exatamente	
  o	
  que	
  esse	
  código	
  todo	
  
está	
  fazendo,	
  então	
  vamos	
  passar	
  diretamente	
  pros	
  testes,	
  pra	
  ver	
  esses	
  novos	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   20	
  
métodos	
  sendo	
  exercitados.	
  Em	
  todos	
  os	
  nossos	
  testes	
  vamos,	
  utilizar	
  um	
  objeto	
  
conta,	
  então	
  em	
  vez	
  de	
  recriar	
  esse	
  objeto	
  a	
  cada	
  teste,	
  vamos	
  ser	
  inteligentes	
  
definir	
  uma	
  variável	
  de	
  instância	
  Conta	
  no	
  nosso	
  teste	
  e	
  implementar	
  o	
  método	
  
“setUp”	
  que	
  cria	
  a	
  conta	
  para	
  não	
  repetirmos	
  essa	
  operação:	
  
Listagem	
  8	
  –	
  ContaTest.h	
  
#import <SenTestingKit/SenTestingKit.h>
@class Conta;
@interface ContaTest : SenTestCase {
Conta * conta;
}
@end
Adicionamos	
  a	
  definição	
  da	
  variável	
  de	
  instância	
  na	
  classe,	
  como	
  esperado,	
  mas	
  o	
  
que	
  é	
  esse	
  “@class”	
  que	
  também	
  está	
  aí?	
  O	
  @class	
  em	
  Objective-­‐C	
  é	
  uma	
  
“forward	
  reference”	
  e	
  normalmente	
  é	
  utilizado	
  em	
  arquivos	
  “.h”	
  para	
  que	
  você	
  
diga	
  que	
  o	
  seu	
  arquivo	
  depende	
  de	
  uma	
  classe	
  em	
  específico,	
  mas	
  não	
  vai	
  fazer	
  o	
  
“#import”	
  dessa	
  classe	
  aqui,	
  vai	
  deixar	
  pra	
  importar	
  o	
  arquivo	
  da	
  classe	
  somente	
  
no	
  seu	
  “.m”.	
  Se	
  você	
  não	
  colocar	
  o	
  @class	
  nem	
  o	
  “#import”	
  pra	
  o	
  arquivo	
  da	
  
classe	
  não	
  vai	
  ser	
  possível	
  compilar	
  o	
  código.	
  
Um	
  detalhe	
  importante	
  do	
  “#import”	
  é	
  que	
  quando	
  o	
  texto	
  que	
  vem	
  após	
  ele	
  está	
  
entre	
  “<>”	
  (como	
  em	
  #import <SenTestingKit/SenTestingKit.h>),	
  isso	
  
indica	
  ao	
  compilador	
  que	
  ele	
  deve	
  procurar	
  esse	
  arquivo	
  no	
  “load	
  path”	
  do	
  
sistema	
  operacional,	
  os	
  lugares	
  onde	
  ficam	
  os	
  arquivos	
  “.h”	
  do	
  mesmo.	
  Quando	
  o	
  
“#import”	
  aparece	
  usando	
  aspas	
  no	
  conteúdo	
  a	
  ser	
  importado,	
  quer	
  dizer	
  que	
  ele	
  
deve	
  procurar	
  dentro	
  dos	
  arquivos	
  locais	
  do	
  projeto	
  (como	
  em	
  #import
"Conta.h").	
  
Vejamos	
  agora	
  a	
  implementação	
  atual	
  dos	
  testes:	
  
Listagem	
  	
  9	
  –	
  ContaTest.m	
  
#import "ContaTest.h"
#import "Conta.h"
@implementation ContaTest
- (void) setUp {
conta = [[Conta alloc] init];
[conta depositar: 200];
}
- (void) testDepositarComSucesso {
[conta depositar:150];
STAssertTrue( conta.saldo == 350, @"Saldo final deve ser
350" );
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   21	
  
}
- (void) testDepositarComFalha {
[conta depositar:-150];
STAssertTrue( conta.saldo == 200, @"Valor do saldo não
deve ter se modificado" );
}
- (void) testSacarComSucesso {
[conta sacar:150];
STAssertTrue( conta.saldo == 50, @"O saldo atual deve ser
50" );
}
- (void) testSacarComValorMaior {
[conta sacar: 250];
STAssertTrue( conta.saldo == 200, @"O saldo atual não deve
ter se modificado" );
}
- (void) testSacarComValorNegativo {
[conta sacar: -100];
STAssertTrue( conta.saldo == 200, @"O saldo atual não deve
ter se modificado" );
}
- (void) testTransferirComSucesso {
Conta * destino = [[Conta alloc] init];
[conta transferir:150 para: destino];
STAssertTrue( conta.saldo == 50, @"O saldo da conta origem
deve ser 50" );
STAssertTrue( destino.saldo == 150, @"O saldo da conta
destino deve ser 250" );
}
- (void) testTransferirComFalha {
Conta * destino = [[Conta alloc] init];
[ conta transferir:250 para: destino ];
STAssertTrue( conta.saldo == 200, @"O saldo da conta
origem deve ser 50" );
STAssertTrue( destino.saldo == 0, @"O saldo da conta
destino deve ser 250" );
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   22	
  
}
@end
Temos	
  então	
  vários	
  testes	
  para	
  a	
  implementação	
  das	
  funcionalidades	
  da	
  nossa	
  
classe	
  conta,	
  eles	
  são	
  bem	
  simples,	
  mas	
  tem	
  duas	
  coisas	
  importantes	
  que	
  não	
  
discutimos	
  ainda,	
  a	
  primeira	
  é	
  essa:	
  
conta.saldo == 200
Antes,	
  no	
  nosso	
  teste,	
  fazíamos	
  a	
  chamada	
  assim:	
  
[conta saldo] == 200
Em	
  Objective-­‐C,	
  se	
  você	
  tem	
  um	
  método	
  que	
  não	
  recebe	
  parâmetros	
  e	
  retorna	
  
um	
  valor,	
  esse	
  método	
  pode	
  ser	
  chamado	
  como	
  se	
  ele	
  fosse	
  uma	
  propriedade	
  do	
  
seu	
  objeto,	
  sem	
  que	
  você	
  tenha	
  que	
  fazer	
  uma	
  invocação	
  explícita	
  do	
  mesmo,	
  
então	
  “conta.saldo”	
  é	
  a	
  mesma	
  coisa	
  que	
  escrever	
  “[conta	
  saldo]”,	
  o	
  compilador	
  
vai	
  fazer	
  a	
  mágica	
  de	
  transformar	
  o	
  primeiro	
  no	
  segundo	
  pra	
  você.	
  
Já	
  o	
  segundo	
  caso:	
  
[ conta transferir:250 para: destino ]
Aqui	
  nós	
  vemos	
  um	
  exemplo	
  da	
  chamada	
  do	
  método	
  “transferir:para:”,	
  junto	
  
com	
  o	
  transferir	
  nós	
  temos	
  o	
  valor	
  que	
  vai	
  ser	
  transferido	
  e	
  logo	
  depois	
  de	
  para	
  
temos	
  o	
  objeto	
  que	
  vai	
  receber	
  a	
  transferência,	
  veja	
  que	
  não	
  existem	
  vírgulas	
  
separando	
  os	
  parâmetros,	
  eles	
  são	
  separados	
  normalmente	
  pelos	
  espaços	
  entre	
  
os	
  nomes	
  que	
  formam	
  o	
  método	
  e	
  os	
  parâmetros	
  passados.	
  
Criando	
  um	
  “construtor”	
  para	
  o	
  nosso	
  objeto	
  conta	
  
Como	
  já	
  comentamos	
  antes,	
  o	
  par	
  “[[Conta	
  alloc]	
  init]”	
  serve	
  pra	
  criar	
  o	
  objeto	
  e	
  
inicializá-­‐lo	
  dentro	
  do	
  projeto,	
  mas	
  e	
  se	
  nós	
  quisermos	
  definir	
  uma	
  forma	
  
personalizada?	
  Simples,	
  criamos	
  um	
  método	
  de	
  inicialização.	
  No	
  nosso	
  caso	
  
queremos	
  poder	
  criar	
  contas	
  com	
  um	
  saldo	
  que	
  seja	
  diferente	
  de	
  zero.	
  
Começamos	
  por	
  definir	
  o	
  método	
  “initWithSaldo”	
  em	
  “Conta.h”:	
  
Listagem	
  10	
  –	
  Conta.h	
  –	
  declarando	
  o	
  método	
  initWithSaldo	
  
#import <Cocoa/Cocoa.h>
@interface Conta : NSObject {
float saldo;
}
- (Conta *) initWithSaldo: (float) valor;
- (BOOL) depositar: (float) valor;
- (BOOL) sacar: (float) valor;
- (BOOL) transferir: (float) valor para: (Conta *) destino;
- (float) saldo;
@end
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   23	
  
Como	
  não	
  existem	
  construtores	
  realmente	
  dentro	
  da	
  linguagem,	
  o	
  que	
  nós	
  
fazemos	
  é	
  definir	
  métodos	
  que	
  inicializem	
  o	
  objeto	
  com	
  o	
  valor	
  que	
  nos	
  
interessa,	
  vejamos	
  a	
  implementação	
  agora	
  pra	
  entender	
  um	
  pouco	
  mais	
  o	
  que	
  
está	
  acontecendo	
  e	
  porque	
  é	
  necessário	
  criar	
  esses	
  métodos:	
  
Listagem	
  11	
  –	
  Conta.m	
  	
  
#import "Conta.h"
@implementation Conta
- (Conta *) initWithSaldo:(float)valor {
if ( self = [ self init]) {
saldo = valor;
}
return self;
}
// todo aquele código que você já viu
@end
Mais	
  um	
  caso	
  de	
  idioma	
  da	
  linguagem	
  surge	
  então	
  pra	
  nós	
  nesse	
  momento:	
  
if ( self = [ self init]) {
Por	
  mais	
  estranho	
  que	
  pareça,	
  esse	
  código	
  está	
  realmente	
  atribuindo	
  um	
  valor	
  a	
  
variável	
  “self”	
  (“self”	
  é	
  equivalente	
  ao	
  “this”	
  em	
  Java	
  e	
  C#,	
  é	
  uma	
  referência	
  para	
  
o	
  objeto	
  onde	
  o	
  método	
  em	
  execução	
  atual	
  foi	
  chamado)	
  dentro	
  do	
  seu	
  objeto.	
  	
  
Mas	
  porque	
  alguém	
  iria	
  querer	
  fazer	
  isso?	
  
Na	
  implementação	
  da	
  Apple	
  do	
  Objective-­‐C	
  existe	
  um	
  conceito	
  chamado	
  de	
  
“class-­‐clusters”.	
  Quando	
  você	
  cria	
  um	
  objeto	
  do	
  tipo	
  NSString,	
  o	
  que	
  você	
  recebe	
  
pode	
  não	
  ser	
  exatamente	
  um	
  NSString,	
  mas	
  uma	
  subclasse	
  dele.	
  As	
  classes	
  que	
  
nós	
  vemos	
  “do	
  lado	
  de	
  fora”	
  funcionam	
  apenas	
  como	
  um	
  meio	
  pra	
  se	
  acessar	
  as	
  
classes	
  que	
  fazem	
  realmente	
  o	
  trabalho,	
  mas	
  esses	
  detalhes	
  de	
  implementação	
  
ficam	
  escondidos	
  graças	
  a	
  essa	
  pequena	
  mágica	
  do	
  método	
  init	
  (atribuir	
  um	
  novo	
  
valor	
  a	
  self	
  e	
  retornar	
  esse	
  valor).	
  
No	
  caso	
  da	
  nossa	
  classe	
  não	
  seria	
  necessário	
  fazer	
  essa	
  mágica,	
  já	
  que	
  estamos	
  
realmente	
  retornando	
  uma	
  conta,	
  mas	
  o	
  ideal	
  é	
  que	
  você	
  construa	
  todos	
  os	
  seus	
  
inicializadores	
  dessa	
  forma	
  para	
  que	
  quando	
  for	
  criar	
  uma	
  subclasse	
  de	
  uma	
  
classe	
  padrão	
  da	
  linguagem	
  não	
  se	
  esquecer	
  e	
  terminar	
  com	
  bugs	
  estranhos	
  no	
  
seu	
  código.	
  
Outra	
  coisa	
  importante	
  também	
  é	
  lembrar-­‐se	
  de	
  chamar	
  o	
  método	
  “init”	
  da	
  sua	
  
classe,	
  se	
  você	
  estiver	
  implementando	
  um	
  novo	
  inicializador	
  (como	
  nós	
  fazemos	
  
nesse	
  código)	
  ou	
  chamar	
  o	
  método	
  init	
  da	
  sua	
  superclasse	
  (com	
  [super	
  init])	
  se	
  
você	
  estiver	
  sobrescrevendo	
  o	
  método	
  “init”,	
  assim	
  você	
  não	
  perde	
  o	
  código	
  de	
  
inicialização	
  que	
  já	
  tenha	
  sido	
  implementado	
  na	
  classe	
  atual	
  e	
  nas	
  suas	
  
superclasses.	
  
Definindo	
  propriedades	
  automaticamente	
  nos	
  objetos	
  
Nós	
  vimos	
  que	
  o	
  compilador	
  é	
  inteligente	
  o	
  suficiente	
  pra	
  aceitar	
  que	
  “[conta	
  
saldo]”	
  seja	
  chamado	
  como	
  “conta.saldo”,	
  mas	
  além	
  disso	
  nós	
  também	
  podemos	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   24	
  
instruir	
  o	
  compilador	
  para	
  que	
  ele	
  gere	
  os	
  métodos	
  de	
  acesso	
  para	
  as	
  
propriedades	
  dos	
  nossos	
  objetos	
  automaticamente	
  (pense	
  no	
  “generate	
  getters	
  
and	
  setters”	
  do	
  Eclipse	
  ou	
  attr_accessor	
  em	
  Ruby).	
  Pra	
  isso,	
  vamos	
  definir	
  novas	
  
propriedades	
  na	
  nossa	
  classe,	
  “agencia”	
  e	
  	
  “conta”.	
  Vejamos	
  como	
  fica	
  o	
  nosso	
  
“Conta.h”	
  agora:	
  
Listagem	
  12	
  –	
  Conta.h	
  com	
  as	
  novas	
  propriedades	
  definidas	
  
#import <Cocoa/Cocoa.h>
@interface Conta : NSObject {
float saldo;
NSString * conta;
NSString * agencia;
}
@property (copy, nonatomic) NSString * conta;
@property (copy, nonatomic) NSString * agencia;
@property (readonly) float saldo;
- (Conta *) initWithSaldo: (float) valor;
- (BOOL) depositar: (float) valor;
- (BOOL) sacar: (float) valor;
- (BOOL) transferir: (float) valor para: (Conta *) destino;
@end
Nós	
  definimos	
  as	
  duas	
  variáveis	
  de	
  instância,	
  “agencia”	
  e	
  “conta”,	
  e	
  logo	
  depois	
  
temos	
  as	
  declarações	
  das	
  propriedades,	
  com	
  “@property”:	
  
@property (copy, nonatomic) NSString * conta;
Isso	
  indica	
  ao	
  compilador	
  que	
  nós	
  vamos	
  ter	
  os	
  métodos	
  abaixo	
  definidos:	
  
-­‐ (NSString	
  *	
  )	
  conta;	
  
-­‐ (void)	
  setConta:	
  (	
  NSString	
  *	
  );	
  
As	
  instruções	
  “copy”	
  e	
  “nonatomic”	
  são	
  atributos	
  que	
  vão	
  ser	
  utilizados	
  na	
  
geração	
  da	
  implementação	
  dos	
  métodos.	
  	
  
-­‐ “copy”	
  indica	
  que	
  quando	
  um	
  objeto	
  for	
  recebido	
  como	
  parâmetro,	
  deve	
  
ser	
  criada	
  uma	
  cópia	
  desse	
  objeto	
  e	
  essa	
  cópia	
  é	
  quem	
  vai	
  ser	
  atribuída	
  a	
  
variável	
  de	
  instância,	
  isso	
  é	
  necessário	
  especialmente	
  se	
  você	
  está	
  
recebendo	
  dados	
  da	
  interface,	
  pois	
  os	
  strings	
  que	
  vem	
  dela	
  podem	
  ser	
  
recolhidos	
  da	
  memória	
  a	
  qualquer	
  momento	
  nos	
  ambientes	
  onde	
  não	
  há	
  
coletor	
  de	
  lixo,	
  como	
  iPads	
  e	
  iPhones.	
  
-­‐ “nonatomic”	
  indica	
  que	
  os	
  métodos	
  gerados	
  não	
  vão	
  fazer	
  nenhum	
  
controle	
  sobre	
  o	
  acesso	
  de	
  forma	
  concorrente.	
  Esse	
  normalmente	
  é	
  o	
  caso	
  
pra	
  maior	
  parte	
  das	
  aplicações,	
  mas	
  se	
  você	
  vai	
  utilizar	
  esse	
  objeto	
  em	
  um	
  
ambiente	
  com	
  concorrência,	
  onde	
  várias	
  threads	
  vão	
  acessar	
  o	
  mesmo	
  
objeto	
  e	
  chamar	
  seus	
  métodos,	
  deve	
  remover	
  isso.	
  
-­‐ “readonly”	
  indica	
  que	
  apenas	
  o	
  método	
  “getter”,	
  que	
  lê	
  o	
  valor	
  da	
  variável,	
  
vai	
  ser	
  gerado,	
  o	
  método	
  set,	
  que	
  altera	
  o	
  valor	
  da	
  variável	
  não	
  vai	
  ser	
  
gerado.	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   25	
  
Com	
  os	
  métodos	
  definidos,	
  agora	
  voltamos	
  pra	
  “Conta.m”	
  pra	
  declarar	
  o	
  código	
  
que	
  vai	
  fazer	
  com	
  que	
  os	
  métodos	
  sejam	
  realmente	
  gerados,	
  vejamos	
  como	
  fica	
  o	
  
código	
  agora:	
  
Listagem	
  13	
  –	
  Conta.m	
  com	
  a	
  definição	
  das	
  propriedades	
  e	
  gerenciamento	
  de	
  
memória	
  
#import "Conta.h"
@implementation Conta
@synthesize agencia, conta, saldo;
- (void) dealloc {
[ self.agencia release ];
[ self.conta release ];
[ super dealloc ];
}
// todo o resto do código que você já conhece aqui
@end
A	
  mágica	
  de	
  verdade	
  vive	
  no	
  “@synthesize”,	
  ele	
  instrui	
  o	
  compilador	
  a	
  ler	
  as	
  
informações	
  das	
  propriedades	
  definidas	
  através	
  de	
  “@property”	
  e	
  gerar	
  os	
  
métodos.	
  Junto	
  com	
  isso	
  chegamos	
  a	
  um	
  detalhe	
  importante	
  da	
  programação	
  
com	
  Objective-­‐C,	
  especialmente	
  se	
  você	
  estiver	
  planejando	
  programar	
  para	
  iOS,	
  o	
  
gerenciamento	
  de	
  memória.	
  
Com	
  a	
  definição	
  das	
  propriedades	
  nós	
  definimos	
  também	
  o	
  método	
  “dealloc”	
  que	
  
é	
  chamado	
  quando	
  um	
  objeto	
  vai	
  ser	
  removido	
  da	
  memória,	
  para	
  que	
  ele	
  possa	
  
limpar	
  da	
  memória	
  também	
  os	
  objetos	
  para	
  os	
  quais	
  ele	
  aponta.	
  Quando	
  você	
  
está	
  programando	
  em	
  Objective-­‐C	
  para	
  iOS,	
  não	
  existe	
  um	
  coletor	
  de	
  lixo	
  
automático,	
  liberar	
  a	
  memória	
  é	
  responsabilidade	
  do	
  programador,	
  então	
  é	
  
necessário	
  que	
  você	
  tome	
  cuidado	
  para	
  não	
  vazar	
  memória	
  no	
  seu	
  código	
  e	
  
estourar	
  a	
  memória	
  do	
  dispositivo.	
  
Em	
  Objective-­‐C	
  o	
  controle	
  de	
  memória,	
  quando	
  não	
  é	
  feito	
  através	
  do	
  coletor	
  de	
  
lixo,	
  acontece	
  através	
  da	
  contagem	
  de	
  referencias.	
  Sempre	
  que	
  você	
  cria	
  um	
  
objeto	
  usando	
  “alloc”	
  ou	
  “new”	
  esse	
  objeto	
  fica	
  com	
  o	
  contador	
  de	
  referencias	
  em	
  
1	
  (um),	
  cada	
  vez	
  que	
  você	
  chama	
  “retain”	
  no	
  objeto	
  (como	
  em	
  “[objeto	
  retain]”)	
  
esse	
  contador	
  aumenta	
  em	
  um	
  e	
  cada	
  vês	
  que	
  você	
  chama	
  “release”	
  (como	
  em	
  
“[objeto	
  release]”)	
  o	
  contador	
  diminui	
  em	
  1.	
  Quando	
  o	
  contador	
  de	
  referencias	
  
atingir	
  0,	
  o	
  objeto	
  é	
  removido	
  da	
  memória.	
  
No	
  nosso	
  caso,	
  as	
  propriedades	
  “conta”	
  e	
  “agencia”	
  são	
  definidas	
  como	
  “copy”,	
  
isso	
  quer	
  dizer	
  que	
  o	
  objeto	
  que	
  vai	
  ser	
  colocado	
  na	
  variável	
  de	
  instância	
  vai	
  ser	
  
clonado	
  e	
  o	
  clone	
  é	
  o	
  objeto	
  que	
  vai	
  finalmente	
  ficar	
  disponível	
  para	
  a	
  nossa	
  
classe.	
  Como	
  o	
  clone	
  é	
  um	
  objeto	
  recém-­‐criado	
  com	
  base	
  em	
  outro	
  objeto	
  a	
  sua	
  
contagem	
  de	
  referencias	
  é	
  1	
  (um),	
  o	
  que	
  quer	
  dizer	
  que	
  quando	
  chamarmos	
  
“release”	
  neles,	
  eles	
  vão	
  ser	
  removidos	
  da	
  memória.	
  
Pra	
  limpar	
  a	
  memória	
  que	
  estamos	
  usando,	
  precisamos	
  ajustar	
  o	
  nosso	
  teste	
  
para	
  fazer	
  o	
  “release”	
  dos	
  objetos	
  conta	
  que	
  estão	
  sendo	
  criados.	
  Vamos	
  fazer	
  o	
  
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   26	
  
release	
  da	
  variável	
  de	
  instância	
  conta	
  no	
  método	
  tearDown	
  e	
  da	
  conta	
  destino	
  
em	
  cada	
  um	
  dos	
  testes,	
  vejamos	
  o	
  que	
  muda	
  na	
  nossa	
  classe	
  teste:	
  
Listagem	
  14	
  –	
  ContaTest.m	
  com	
  o	
  código	
  de	
  gerenciamento	
  de	
  memória	
  
@implementation ContaTest
//métodos não mostrados aqui não foram alterados
- (void) tearDown {
[ conta release ];
}
- (void) testTransferirComSucesso {
Conta * destino = [[Conta alloc] initWithSaldo: 100 ];
[conta transferir:150 para: destino];
STAssertTrue( conta.saldo == 50, @"O saldo da conta origem
deve ser 50" );
STAssertTrue( destino.saldo == 250, @"O saldo da conta
destino deve ser 250" );
[ destino release ];
}
- (void) testTransferirComFalha {
Conta * destino = [[Conta alloc] init];
[ conta transferir:250 para: destino ];
STAssertTrue( conta.saldo == 200, @"O saldo da conta
origem deve ser 50" );
STAssertTrue( destino.saldo == 0, @"O saldo da conta
destino deve ser 250" );
[ destino release ];
}
- (void) testSetContaEAgencia {
conta.agencia = @"1111-0";
conta.conta = @"10.000-9";
STAssertEqualObjects( conta.agencia, @"1111-0", @"O valor
deve ser igual" );
STAssertEqualObjects( conta.conta, @"10.000-9", @"O valor
deve ser igual" );
}
@end
Curso	
  de	
  desenvolvimento	
  de	
  aplicações	
  para	
  iOS	
  usando	
  Objective-­‐C	
  
Maurício	
  Linhares	
  
	
  
	
   27	
  
Adicionamos	
  a	
  nossa	
  implementação	
  o	
  método	
  “tearDown”	
  que	
  envia	
  um	
  
“release”	
  para	
  o	
  objeto	
  conta	
  e	
  também	
  fazemos	
  o	
  release	
  dos	
  objetos	
  destino	
  
criados	
  nos	
  testes	
  de	
  transferência.	
  Você	
  nunca	
  deve	
  chamar	
  o	
  método	
  dealloc	
  
diretamente	
  nos	
  seus	
  objetos,	
  sempre	
  chame	
  release	
  e	
  deixe	
  que	
  o	
  próprio	
  
runtime	
  do	
  Objective-­‐C	
  vai	
  fazer	
  a	
  chamada	
  a	
  dealloc	
  quando	
  for	
  a	
  hora	
  correta.	
  
É	
  possível	
  definir	
  algumas	
  regrinhas	
  básicas	
  na	
  hora	
  de	
  lidar	
  com	
  a	
  gerência	
  de	
  
memória	
  em	
  aplicações	
  escritas	
  em	
  Objective-­‐C:	
  
• Se	
  você	
  pegou	
  um	
  objeto	
  através	
  de	
  “alloc/new/copy”,	
  esse	
  objeto	
  tem	
  
um	
  contador	
  de	
  1	
  e	
  você	
  deve	
  se	
  lembrar	
  de	
  liberar	
  esse	
  objeto	
  quando	
  
ele	
  não	
  for	
  mais	
  necessário;	
  
• Se	
  você	
  pegou	
  um	
  objeto	
  de	
  outro	
  lugar,	
  assuma	
  que	
  ele	
  tem	
  um	
  contador	
  
de	
  1,	
  se	
  você	
  só	
  vai	
  usá-­‐lo	
  e	
  deixar	
  ele	
  pra	
  lá,	
  não	
  faça	
  nada	
  com	
  ele,	
  quem	
  
passou	
  ele	
  pra	
  você	
  provavelmente	
  vai	
  limpá-­‐lo	
  quando	
  for	
  necessário.	
  	
  
• Se	
  você	
  precisa	
  manter	
  um	
  objeto	
  recebido	
  de	
  outro	
  lugar	
  para	
  usá-­‐lo	
  em	
  
outro	
  momento,	
  chame	
  “retain”	
  nele	
  para	
  que	
  o	
  contador	
  aumente	
  para	
  
“2”,	
  assim	
  quando	
  quem	
  lhe	
  passou	
  esse	
  objeto	
  chamar	
  “release”	
  nele	
  o	
  
contador	
  vai	
  baixar	
  pra	
  “1”	
  e	
  o	
  objeto	
  ainda	
  não	
  vai	
  ser	
  liberado	
  da	
  
memória.	
  	
  
• Sempre	
  que	
  você	
  dá	
  “retain”	
  em	
  um	
  objeto,	
  deve	
  garantir	
  que	
  vai	
  dar	
  um	
  
“release”	
  nele	
  em	
  algum	
  momento,	
  se	
  você	
  não	
  der	
  o	
  “release”,	
  com	
  
certeza	
  vai	
  estar	
  vazando	
  memória	
  na	
  sua	
  aplicação;	
  
Gerenciamento	
  de	
  memória	
  é	
  um	
  tópico	
  longo	
  e	
  vamos	
  nos	
  aprofundar	
  mais	
  nele	
  
conforme	
  avançamos	
  para	
  a	
  construção	
  das	
  nossas	
  aplicações	
  para	
  iOS,	
  essa	
  
introdução	
  é	
  apenas	
  para	
  que	
  você	
  entenda	
  o	
  básico	
  de	
  como	
  esse	
  conceito	
  
funciona	
  dentro	
  da	
  linguagem.	
  

Mais conteúdo relacionado

Mais procurados (8)

Aula 7.0 android 02 - primeiro programa calculadora
Aula 7.0   android 02 - primeiro programa calculadoraAula 7.0   android 02 - primeiro programa calculadora
Aula 7.0 android 02 - primeiro programa calculadora
 
Apostila android
Apostila androidApostila android
Apostila android
 
Tutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para AndroidTutorial - Como criar sua primeira app para Android
Tutorial - Como criar sua primeira app para Android
 
Apostila de-corel-draw
Apostila de-corel-drawApostila de-corel-draw
Apostila de-corel-draw
 
Apostila de corel draw
Apostila de corel drawApostila de corel draw
Apostila de corel draw
 
Apostila de corel draw
Apostila de corel drawApostila de corel draw
Apostila de corel draw
 
Tutorial vb projeto em vb.net
Tutorial vb projeto em vb.netTutorial vb projeto em vb.net
Tutorial vb projeto em vb.net
 
Bada
BadaBada
Bada
 

Destaque

XML - eXtensible Markup Language
XML - eXtensible Markup LanguageXML - eXtensible Markup Language
XML - eXtensible Markup Language
elliando dias
 
Arquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemanticaArquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemantica
Sergio Crespo
 

Destaque (20)

Objective-C
Objective-CObjective-C
Objective-C
 
Curso de Desenvolvimento Web - Módulo 03 - JavaScript
Curso de Desenvolvimento Web - Módulo 03 - JavaScriptCurso de Desenvolvimento Web - Módulo 03 - JavaScript
Curso de Desenvolvimento Web - Módulo 03 - JavaScript
 
XML: Uma Introdução Prática (2001)
XML: Uma Introdução Prática (2001)XML: Uma Introdução Prática (2001)
XML: Uma Introdução Prática (2001)
 
XML - eXtensible Markup Language
XML - eXtensible Markup LanguageXML - eXtensible Markup Language
XML - eXtensible Markup Language
 
Arquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemanticaArquitetura: XML + RDF ate WebSemantica
Arquitetura: XML + RDF ate WebSemantica
 
eXtensible Markup Language (XML)
eXtensible Markup Language (XML)eXtensible Markup Language (XML)
eXtensible Markup Language (XML)
 
Xml100 1
Xml100 1Xml100 1
Xml100 1
 
XML & HTML
XML & HTMLXML & HTML
XML & HTML
 
Aula Introdução a Linguagem XML
Aula Introdução a Linguagem XMLAula Introdução a Linguagem XML
Aula Introdução a Linguagem XML
 
Banco de Dados XML
Banco de Dados XMLBanco de Dados XML
Banco de Dados XML
 
XML e Banco de Dados XML Nativo
XML e Banco de Dados XML NativoXML e Banco de Dados XML Nativo
XML e Banco de Dados XML Nativo
 
Apostila XML, DTD, XSD e XSLT
Apostila XML, DTD, XSD e XSLTApostila XML, DTD, XSD e XSLT
Apostila XML, DTD, XSD e XSLT
 
Engenharia Social
Engenharia SocialEngenharia Social
Engenharia Social
 
Espionagem e Software Livre
Espionagem e Software LivreEspionagem e Software Livre
Espionagem e Software Livre
 
Html5 - O futuro da Web
Html5 - O futuro da WebHtml5 - O futuro da Web
Html5 - O futuro da Web
 
O que há de novo no PHP 5.3
O que há de novo no PHP 5.3O que há de novo no PHP 5.3
O que há de novo no PHP 5.3
 
Introdução ao CSS
Introdução ao CSSIntrodução ao CSS
Introdução ao CSS
 
Html5 - Estrutura Básica
Html5 - Estrutura BásicaHtml5 - Estrutura Básica
Html5 - Estrutura Básica
 
Certificacoes Desenvolvedores
Certificacoes DesenvolvedoresCertificacoes Desenvolvedores
Certificacoes Desenvolvedores
 
HTML5 & CSS3 - A Evolução da Web
HTML5 & CSS3 - A Evolução da WebHTML5 & CSS3 - A Evolução da Web
HTML5 & CSS3 - A Evolução da Web
 

Semelhante a Curso de desenvolvimento de aplicações para iOS com Objective-C

Guia rapido total cross studio
Guia rapido total cross studioGuia rapido total cross studio
Guia rapido total cross studio
Rafael Din
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI Android
Vinícius Thiengo
 

Semelhante a Curso de desenvolvimento de aplicações para iOS com Objective-C (20)

Android Core Aula 6 - Desenvolvimento de aplicações Android
Android Core Aula 6 -  Desenvolvimento de aplicações AndroidAndroid Core Aula 6 -  Desenvolvimento de aplicações Android
Android Core Aula 6 - Desenvolvimento de aplicações Android
 
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
Otimização, dicas de implementação, como resolver problemas by Adriano Santan...
 
Apostila android
Apostila androidApostila android
Apostila android
 
Apostila android
Apostila androidApostila android
Apostila android
 
Ionic + Cordova para Desenvolvimento Mobile
Ionic + Cordova para Desenvolvimento MobileIonic + Cordova para Desenvolvimento Mobile
Ionic + Cordova para Desenvolvimento Mobile
 
Microsoft visual c_
Microsoft visual c_Microsoft visual c_
Microsoft visual c_
 
Microsoft visual c_
Microsoft visual c_Microsoft visual c_
Microsoft visual c_
 
Aula1
Aula1Aula1
Aula1
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POO
 
Apostila de-delphi
Apostila de-delphiApostila de-delphi
Apostila de-delphi
 
Aula02 android hands_on
Aula02 android hands_onAula02 android hands_on
Aula02 android hands_on
 
Aula1
Aula1Aula1
Aula1
 
Workshop frontend
Workshop   frontendWorkshop   frontend
Workshop frontend
 
Guia rapido total cross studio
Guia rapido total cross studioGuia rapido total cross studio
Guia rapido total cross studio
 
Principais dicas para UIs do Android
Principais dicas para UIs do AndroidPrincipais dicas para UIs do Android
Principais dicas para UIs do Android
 
Visual Basic Básico
Visual Basic BásicoVisual Basic Básico
Visual Basic Básico
 
Vbasic6
Vbasic6Vbasic6
Vbasic6
 
Introdução Ao Desenvolvimento Para Iphone
Introdução Ao Desenvolvimento Para IphoneIntrodução Ao Desenvolvimento Para Iphone
Introdução Ao Desenvolvimento Para Iphone
 
Data Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI AndroidData Binding Para Vinculo de Dados na UI Android
Data Binding Para Vinculo de Dados na UI Android
 
Configurando o ambiente para desenvolvimento Android
Configurando o ambiente para desenvolvimento AndroidConfigurando o ambiente para desenvolvimento Android
Configurando o ambiente para desenvolvimento Android
 

Mais de Maurício Linhares

Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleções
Maurício Linhares
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
Maurício Linhares
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratos
Maurício Linhares
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
Maurício Linhares
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
Maurício Linhares
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
Maurício Linhares
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
Maurício Linhares
 

Mais de Maurício Linhares (20)

Mercado de TI
Mercado de TIMercado de TI
Mercado de TI
 
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDropUnindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
 
Aprendendo ruby
Aprendendo rubyAprendendo ruby
Aprendendo ruby
 
Curso java 07 - exceções
Curso java   07 - exceçõesCurso java   07 - exceções
Curso java 07 - exceções
 
Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleções
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratos
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
 
Curso java 02 - variáveis
Curso java   02 - variáveisCurso java   02 - variáveis
Curso java 02 - variáveis
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
Extreme programming
Extreme programmingExtreme programming
Extreme programming
 
Feature Driven Development
Feature Driven DevelopmentFeature Driven Development
Feature Driven Development
 
Migrando pra Scala
Migrando pra ScalaMigrando pra Scala
Migrando pra Scala
 
Outsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvemOutsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvem
 
Mercado hoje
Mercado hojeMercado hoje
Mercado hoje
 
Análise de sistemas oo 1
Análise de sistemas oo   1Análise de sistemas oo   1
Análise de sistemas oo 1
 
Revisão html e java script
Revisão html e java scriptRevisão html e java script
Revisão html e java script
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
 

Curso de desenvolvimento de aplicações para iOS com Objective-C

  • 1. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       1   Desenvolvendo  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares  mauricio.linhares@gmail.com     DESENVOLVIMENTO  DE  APLICAÇÕES  PARA  IOS  USANDO  OBJECTIVE-­‐C   1   INTRODUÇÃO   2   CAPÍTULO  1  -­‐  CONHECENDO  OBJECTIVE-­‐C   3   IMAGEM  1  –  SELEÇÃO  DE  PROJETOS  NO  XCODE   3   IMAGEM  2  –  CRIANDO  O  PROJETO  NO  XCODE     4   IMAGEM  3  –  VISUALIZAÇÃO  INICIAL  DO  PROJETO   5   IMAGEM  4  –  CRIANDO  O  TARGET  QUE  VAI  RODAR  OS  NOSSOS  TESTES   6   IMAGEM  5  –  ADICIONANDO  O  EXECUTÁVEL  DA  APLICAÇÃO  COMO  DEPENDÊNCIA  AO  TARGET  TEST   7   IMAGEM  6  –  CRIANDO  A  NOSSA  PRIMEIRA  CLASSE  EM  OBJECTIVE-­‐C   8   IMAGEM  7  –  CRIANDO  A  NOSSA  PRIMEIRA  CLASSE  EM  OBJECTIVE-­‐C   9   IMAGEM  8  –  VISUALIZAÇÃO  DO  NAVEGADOR  DE  ARQUIVOS  COM  A  CLASSE  CONTA  CRIADA.   9   LISTAGEM  1  –  CONTA.H   9   LISTAGEM  2  –  CONTA.M   11   LISTAGEM  3  –  CONTA.H   11   LISTAGEM  4  –  CONTA.M   12   CRIANDO  O  NOSSO  PRIMEIRO  TESTE  UNITÁRIO   12   IMAGEM  9  –  CRIANDO  O  GRUPO  “TEST”   13   IMAGEM  10  –  CRIANDO  A  CLASSE  DE  TESTES   13   IMAGEM  11  –  SELECIONANDO  OS  TARGETS  DA  CLASSE  DE  TESTES   14   IMPLEMENTANDO  O  NOSSO  PRIMEIRO  TESTE   14   LISTAGEM  5  –  CONTATEST.M   14   IMAGEM  12  –  ALTERANDO  O  TARGET  PADRÃO  PARA  TEST   16   IMAGEM  13  –  DRAG  E  DROP  DO  ARQUIVO  “CONTA.M”  EM  TEST   16   IMAGEM  14  –  INDICAÇÃO  DE  ERROS  DE  BUILD  DO  XCODE   17   IMAGEM  15  –  TELA  DE  ERROS  NO  BUILD  DO  XCODE   18   LISTAGEM  6  –  CONTA.H   18   LISTAGEM  7  –  CONTA.M   19   LISTAGEM  8  –  CONTATEST.H   20   LISTAGEM    9  –  CONTATEST.M   20   CRIANDO  UM  “CONSTRUTOR”  PARA  O  NOSSO  OBJETO  CONTA   22   LISTAGEM  10  –  CONTA.H  –  DECLARANDO  O  MÉTODO  INITWITHSALDO   22   LISTAGEM  11  –  CONTA.M   23   DEFININDO  PROPRIEDADES  AUTOMATICAMENTE  NOS  OBJETOS   23   LISTAGEM  12  –  CONTA.H  COM  AS  NOVAS  PROPRIEDADES  DEFINIDAS   24   LISTAGEM  13  –  CONTA.M  COM  A  DEFINIÇÃO  DAS  PROPRIEDADES  E  GERENCIAMENTO  DE  MEMÓRIA   25   LISTAGEM  14  –  CONTATEST.M  COM  O  CÓDIGO  DE  GERENCIAMENTO  DE  MEMÓRIA   26        
  • 2. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       2   Introdução   Este  material  tem  como  objetivo  servir  de  referência  para  o  curso  de   desenvolvimento  de  aplicações  usando  Objective-­‐C  e  XCode  para  iOS,  o  sistema   operacional    para  dispositivos  móveis  da  Apple,  como  iPhones,  iPods  e  iPads.  Ele   faz  parte  do  material  complementar  para  as  aulas  expositivas  do  curso  de   desenvolvimento  para  iOS.   Para  seguir  esse  material  você  precisa  de  um  computador  com  MacOS  e  XCode   instalados,  além  do  SDK  para  desenvolvimento  de  aplicações  para  iOS.  O  material   também  assume  que  você  já  tem  experiência  com  o  desenvolvimento  de   software  em  ao  menos  uma  linguagem  orientada  a  objetos.     Conceitos  básicos  de  programação  orientada  a  objetos  como  variáveis  de   instância,  métodos,  construtores,  herança,  encapsulamento  não  vão  ser   explicados,  assume-­‐se  que  quem  está  lendo  o  material  já  tem  conhecimento  de   todos  esses  conceitos  que  são  lugar  comum  em  qualquer  linguagem  de   programação  orientada  a  objetos.   Em  várias  partes  do  material  você  vai  encontrar  a  fala  “Abra  o  menu  contextual   do  item  X”  ou  “clique  com  o  botão  direito  em  X”,  isso  quer  dizer  usar  o  botão   direito  do  mouse  (em  um  mouse  comom)  fazer  “Control  +  Click”  no  item   selecionado  ou,  se  você  estiver  usando  um  trackpad  multi-­‐touch,  clicar  com  os   dois  dedos  ao  mesmo  tempo.      
  • 3. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       3   Capítulo  1  -­‐  Conhecendo  Objective-­‐C   O  código  fonte  deste  primeiro  capítulo  está  disponível  em  -­‐   https://github.com/mauricio/capitulo-­‐1-­‐curso-­‐ios     Objective-­‐C  é  uma  linguagem  de  programação  orientada  a  objetos  de  uso  geral  e   é  a  língua  padrão  para  o  desenvolvimento  de  aplicações  para  o  Mac  OS  e  hoje   também  para  o  iOS,  ambos  sistemas  operacionais  desenvolvidos  pela  Apple.  A   linguagem  é  derivada  diretamente  do  C,  com  algumas  características  de   Smalltalk,  como  o  uso  de  parâmetros  dentro  do  nome  do  método  em  vez  de  em   uma  seção  de  parâmetros  no  mesmo.   Vamos  fazer  agora  dar  os  nossos  primeiros  passos  com  o  XCode,  criando  um   projeto.  Abra  o  XCode,  essa  deve  ser  a  primeira  janela  que  você  vai  ver:   Imagem  1  –  Seleção  de  projetos  no  XCode     Nessa  página,  selecione  “Create  a  new  Xcode  project”,  aqui  está  a  próxima  janela   que  você  vai  ver:  
  • 4. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       4   Imagem  2  –  Criando  o  projeto  no  Xcode     Nesse  primeiro  momento,  vamos  iniciar  com  uma  aplicação  para  MacOS,  pra   entender  o  funcionamento  da  linguagem  e  nos  acostumarmos  com  o  Xcode  como   ferramenta.  Após  selecionar  “Mac  OS  X”  -­‐>  “Application”  -­‐>  “Command  Line   Tool”,  além  de  selecionar  “Foundation”  no  campo  de  seleção.  Dê  o  nome     “AprendendoObjectivec”  ao  projeto.   Com  o  projeto  criado,  você  deve  ver  uma  janela  como  essa  agora:  
  • 5. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       5   Imagem  3  –  Visualização  inicial  do  projeto     Um  fator  interessante  ao  se  iniciar  o  desenvolvimento  usando  Xcode  é  que   mesmo  se  parecendo  com  pastas,  “Source”,  “Documentation”,  “External   frameworks  and  libraries”  e  “Products”  não  são  pastas,  mas  “agrupamentos”  de   conteúdo.  Se  você  for  até  a  pasta  que  está  o  projeto,  vai  perceber  que  não   existem  diretórios  equivalentes  a  eles,  isso  acontece  porque  o  Xcode  organiza  os   arquivos  apenas  logicamente  e  não  fisicamente  dentro  do  projeto.   Com  o  nosso  projeto  criado,  vamos  criar  um  target  para  os  testes  unitários  que   vamos  escrever  durante  o  exemplo.  Pra  fazer  isso,  clique  com  o  botão  direito  ou   “Control    +  Click”  no  marcador  “Targets”,  siga  para  “Add”,  depois  “New  Target”.   Você  deve  ver  a  tela  abaixo:  
  • 6. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       6   Imagem  4  –  Criando  o  target  que  vai  rodar  os  nossos  testes     Ao  partir  pra  próxima  tela  você  vai  definir  o  nome  do  target,  coloque  o  nome   Test.  Assim  que  o  target  for  criado,  ele  vai  abrir  a  janela  de  opções  do  mesmo,   nela,  selecione  a  aba  “General”,  clique  no  botão  “+”,  você  deve  ver  então  uma   janela  como  a  imagem  logo  abaixo,  selecione  “AprendendoObjectivec”  e  clique   em  “Add  Target”.  
  • 7. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       7   Imagem  5  –  Adicionando  o  executável  da  aplicação  como  dependência  ao  target   Test     Estamos  agora  finalmente  prontos  pra  começar  a  escrever  o  código  do  projeto.   Para  entender  as  construções  básicas  da  linguagem,  vamos  criar  uma  classe   Conta  que  guarde  os  dados  de  agência,  número  de  conta,  banco  e  saldo.  Além   disso  a  classe  também  vai  conter  os  métodos  para  sacar,  depositar  e  transferir   dinheiro  entre  contas.   Selecione  o  grupo  “Source”  e  abra  o  menu  contextual.  Vá  em  “Add”  -­‐>  “New  File”.   Selecione  “Cocoa  Class”  e  depois  “Objective-­‐C  class”,  como  na  imagem  abaixo:  
  • 8. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       8   Imagem  6  –  Criando  a  nossa  primeira  classe  em  Objective-­‐C     Na  próxima  janela,  coloque  o  nome  da  classe  como  sendo  “Conta.m”  e  marque  o   checkbox  “Also  create  ‘Conta.h’”:  
  • 9. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       9   Imagem  7  –  Criando  a  nossa  primeira  classe  em  Objective-­‐C     Com  a  classe  criada,  você  deve  ver  os  arquivos  no  Xcode  como  na  imagem  abaixo:   Imagem  8  –  visualização  do  navegador  de  arquivos  com  a  classe  Conta  criada.     Olhando  pra  essa  imagem  podemos  ver  que  existe  um  arquivo  “Conta.m”  e  um   arquivo  “Conta.h”,  vejamos  o  que  há  de  código  em  cada  um  desses  arquivos:   Listagem  1  –  Conta.h   #import <Cocoa/Cocoa.h> @interface Conta : NSObject { } @end
  • 10. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       10   Se  você  nunca  programou  em  C  na  vida,  deve  estar  se  perguntando  porque  temos   dois  arquivos  para  uma  única  classe,  um  “.h”  e  outro  “.m”.  O  arquivo  “.h”,   funciona  como  “cabeçalho”  (daí  o  “.h”,  de  “header”),  nele  você  define  a  interface   pública  da  classe,  como  os  atributos  que  ela  tem  e  os  métodos  que  ela   implementa  (e  que  devem  ficar  visíveis  para  terceiros).   Em  Objective-­‐C,  diferentemente  de  Java  e  outras  linguagens,  não  existem   modificadores  de  nível  de  visibilidade  para  as  classes  ou  os  seus  membros  (como   métodos  e  atributos),  tudo  é  “visível”,  mas  apenas  o  que  estiver  definido  no   arquivo  “.h”  fica  realmente  disponível  para  outros  objetos  que  queiram  usar  a   sua  classe.   Olhando  agora  diretamente  para  o  código  fonte,  vemos  o  “#import   <Cocoa/Cocoa.h>”,  isso  quer  dizer  que  a  nossa  classe  está  declarando  que  vai   utilizar  funcionalidades  do  framework  “Cocoa”  (na  verdade  nós  só  precisamos   do  framework  “Foundation”,  mas  vamos  deixar  assim  por  enquanto).  Logo  após   isso  vemos  o  seguinte  código:   @interface  Conta  :  NSObject   Sempre  que  você  vir  um  caractere  “@”  (arroba)  em  código  escrito  em  Objective-­‐ C,  quer  dizer  que  o  que  vem  logo  após  ele  é  uma  extensão  da  linguagem  ao  C.   Opa,  peraí,  como  assim  uma  “extensão  a  linguagem  C”?   Objective-­‐C,  assim  como  C++,  existe  como  uma  extensão  a  linguagem  C.  Você   pode  escrever  código  C  dentro  de  programas  escritos  em  Objective-­‐C  e  o  seu   código  (teoricamente)  vai  compilar  e  funcionar  normalmente.  Os  designers  da   linguagem  resolveram  então  definir  uma  forma  de  deixar  claro  o  que  não  é  “C   puro”  na  linguagem  usando  o  caracter  “@”.  Então  sempre  que  você  vir  o  “@”  já   sabe  que  isso  é  uma  extensão  do  Objective-­‐C  para  adicionar  novos   comportamentos  ao  nosso  querido  e  amado  C.   A  extensão  @interface  diz  que  estamos  definindo  uma  nova  classe  na  linguagem   e  o  que  segue  essa  declaração  é  o  nome  da  classe,  no  nosso  caso  “Conta”.  Logo   após  a  declaração  do  nome  da  classe  o  “:  NSObject”  diz  que  a  nossa  classe  “Conta”   herda  de  “NSObject”.  Diferentemente  de  outras  linguagens  onde  existe  uma  única   classe  raiz  e  mãe  de  todos  os  objetos  (pense  no  Object  de  Java,  Ruby,  C#  e  tantas   outras),  em  Objective-­‐C  você  mesmo  pode  definir  uma  classe  raiz,  mas   normalmente  você  vai  herdar  de  “NSObject”  que  é  a  classe  raiz  do  framework   base  de  Objective-­‐C  utilizado  no  desenvolvimento  de  aplicações  para  o  Mac  OS  e   iOS.  Obviamente,  se  você  não  disser  de  qual  classe  você  herda,  a  sua  classe  se   torna  automaticamente  uma  classe  raiz,  então  lembre-­‐se  sempre  de  definir  a   superclasse  da  sua  classe  ou  simplesmente  coloque  que  ela  herda  de  “NSObject”.   O  par  de  chaves  “{}”  que  vem  logo  após  a  declaração  da  classe  é  o  lugar  onde   você  define  as  variáveis  de  instância  da  sua  classe  e  somente  elas  (não,  não  é   aqui  que  você  coloca  os  métodos).  Todas  as  variáveis  de  instância  precisam  estar   definidas  aqui  no  arquivo  “.h”,  mesmo  aquelas  que  você  queira  deixar  como   “privadas”.   Após  o  par  de  chaves  vem  o  corpo  da  classe,  que  é  o  lugar  onde  você  define  os   métodos  que  essa  classe  implementa  (mas  você  não  os  implementa  aqui,  você  
  • 11. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       11   apenas  define  quais  são  eles).  Não  definir  um  método  aqui  normalmente  faz  com   que  não  seja  possível  pra  que  alguém  o  invoque,  é  uma  das  formas  de  se  criar   métodos  “privados”  em  Objective-­‐C,  já  que  não  existe  esse  conceito  dentro  da   linguagem  em  si.   Listagem  2  –  Conta.m   #import "Conta.h" @implementation Conta @end  No  arquivo  “.m”  você  encontra  agora  o  código  real  da  classe  (mesmo  que  não   tenhamos  colocado  nada  ainda  nele.  Enquanto  que  no  arquivo  “.h”  nós  havíamos   definido  a  @interface  do  código,  agora  estamos  definindo  a  @implementation.   Veja  que  aqui  não  é  mais  necessário  definir  de  qual  classe  a  nossa  classe  herda,  a   definição  fica  apenas  na  interface.     Veja  que  o  código  também  faz  um  “#import”  para  o  arquivo  “.h”,  isso  é  para  que  o   arquivo  de  implementação  possa  ver  as  informações  definidas  na  interface,  como   variáveis  de  instância  e  também  receber  automaticamente  as  dependências  que   já  foram  importadas  no  mesmo.  Em  C  você  faria  o  mesmo  com  #include,  mas  o   #import  vai  um  pouco  mais  longe  e  evita  que  o  mesmo  arquivo  seja  “incluído”   duas  vezes,  um  problema  bem  comum  pra  quem  trabalha  com  C.   Vamos  agora  começar  a  realmente  escrever  código:   Listagem  3  –  Conta.h   #import <Cocoa/Cocoa.h> @interface Conta : NSObject { float saldo; } - (BOOL) depositar:(float)valor; - (float) saldo; @end Agora  a  nossa  classe  conta  tem  uma  variável  de  instância  definida  (do  tipo   “float”),  declaramos  a  existência  do  método  depositar  que  recebe  um  parâmetro   do  tipo  float    e  retorna  um  BOOL,  o  boolean  da  linguagem.  Também  declaramos  o   método  “saldo”  que  vai  ser  a  forma  de  acessar  a  variável  de  instância  “saldo”.  É   possível  acessar  uma  variável  de  instância  de  uma  classe  em  Objective-­‐C   diretamente  de  “fora”  da  classe,  mas  o  melhor  é  fazer  o  acesso  sempre  via   métodos  (ou  as  propriedades  que  veremos  mais  a  frente).   O  sinal  de  “-­‐“  (subtração)  antes  da  definição  do  método  avisa  que  esse  é  um   método  de  instância  (métodos  de  classe  são  definidos  com  um  sinal  de  adição,  o   “+”).  O  tipo  de  retorno  e  o  tipo  dos  parâmetros  recebidos  ficam  sempre  entre   parênteses.     Um  detalhe  importante  na  declaração  de  métodos  em  Objective-­‐C  é  que  o   parâmetro  fica  “dentro”  do  nome  do  método  e  não  após  a  definição  do  nome,  
  • 12. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       12   como  em  Java  ou  Ruby.  Como  o  método  depositar  recebe  um  parâmetro  é   necessário  colocar  os  “:”  para  separar  o  nome  do  parâmetro  que  está  sendo   passado,  depois  vamos  entender  um  pouco  mais  como  se  nomeiam  métodos  em   Objective-­‐C.   Vejamos  então  como  vai  ficar  o  nosso  arquivo  “.m”:   Listagem  4  –  Conta.m   #import "Conta.h" @implementation Conta - (BOOL) depositar: (float) valor { if ( valor > 0 ) { saldo += valor; return YES; } else { return NO; } } - (float) saldo { return saldo; } @end Olhando  pro  código  fonte  você  já  deve  ter  entendido  exatamente  o  que  ele  faz,  se   o  valor  passado  como  parâmetro  for  maior  do  que  zero,  ele  vai  somar  com  o   valor  atual  da  variável  de  instância  “saldo”  e  retornar  YES,  que  é  um  atalho  para  o   valor  BOOL  que  representa  verdadeiro,  se  o  valor  passado  como  parâmetro  for   menor  ou  igual  a  zero  ele  simplesmente  retorna  NO.   Assim  como  em  C,  blocos  de  código  em  Objective-­‐C  ficam  sempre  dentro  de  pares   de  chaves  (“{}”)  e  todas  as  estruturas  de  controle  que  você  conhece  do  C  (ou  Java   e  C#)  existem  exatamente  da  mesma  forma  em  Objective-­‐C.   A  implementação  do  método  “saldo”  é  ainda  mais  trivial,  ela  simplesmente   retorna  o  valor  da  variável  de  instância  diretamente.   Criando  o  nosso  primeiro  teste  unitário   Com  a  nossa  classe  implementada,  agora  é  a  hora  de  escrever  um  teste  para  esse   primeiro  método  implementado.  A  primeira  coisa  a  se  fazer  é  criar  um  novo   grupo  dentro  do  projeto  pra  manter  as  classes  de  teste,  assim  podemos   facilmente  separar  as  classes  dos  seus  testes  na  hora  de  gerar  a  aplicação  final,  já   que  ela  não  precisa  levar  os  testes  consigo.  Clique  com  o  botão  direito  em   “AprendendoObjectivec”,  como  na  imagem  abaixo:  
  • 13. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       13   Imagem  9  –  Criando  o  grupo  “Test”     Com  o  grupo  criado,  clique  com  o  botão  direito  em  “Test”,  selecione  “Add”  e   “New  File”.  Você  vai  criar  uma  classe  de  teste  padrão  do  Cocoa,  como  na  imagem   abaixo:   Imagem  10  –  Criando  a  classe  de  testes     Dê  o  nome  “ContaTest”  a  classe  e  selecione  o  Target  “Test”  apenas,  desmarcando   o  primeiro  Target  que  aparece,  como  na  imagem  abaixo:  
  • 14. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       14   Imagem  11  –  Selecionando  os  targets  da  classe  de  testes     No  caso  dos  testes,  você  normalmente  não  precisa  definir  nada  no  arquivo  “.h”,  já   que  os  métodos  são  chamados  automaticamente,  então  vamos  nos  focar  apenas   no  arquivo  “.m”,  que  é  onde  nós  vamos  realmente  estar  trabalhando.     Implementando  o  nosso  primeiro  teste   Listagem  5  –  ContaTest.m   #import "ContaTest.h" #import "Conta.h" @implementation ContaTest - (void) testDepositarComSucesso { Conta * conta = [[Conta alloc] init]; [conta depositar:200]; STAssertTrue( [conta saldo] == 300, @"O saldo deve ser de 300 para que o teste falhe" ); } @end Assim  como  em  outros  frameworks  de  teste,  o  método  que  define  a   implementação  do  teste  precisa  ter  o  seu  nome  iniciando  com  “test”  e  não   retornar  nada  (por  isso  o  void).  Na  primeira  linha  do  teste  já  temos  vários   detalhes  da  linguagem  pra  entender.     A  primeira  coisa  a  ser  percebida  é  que  a  declaração  da  variável  contém  um  “*”,  se   você  vem  do  C,  sabe  que  isso  quer  dizer  que  essa  variável  é  na  verdade  uma   referencia  (ou  ponteiro)  pra  um  objeto  que  está  em  memória.  Sempre  que  você   define  uma  referencia  pra  uma  variável  em  Objective-­‐C  é  necessário  colocar  o  
  • 15. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       15   “*”,  se  você  não  o  fizer  vai  receber  warnings  do  compilador  e  o  seu  programa  não   vai  funcionar  corretamente.   Ainda  nessa  linha  temos  o  idioma  de  inicialização  de  objetos.  O  que  em  outras   linguagens  de  programação  OO  seria  feito  através  de  um  construtor,  em   Objective-­‐C  se  faz  através  das  chamadas  a  “alloc”,  um  método  de  classe  que   organiza  uma  nova  instância  do  objeto  em  memória  e  retorna  o  objeto  pronto   pra  uso,  e  “init”,  que  executa  finalmente  a  inicialização  do  objeto.  É  possível  usar   também  o  método  de  classe  “new”  em  vez  do  “par”  alloc/init  para  se  criar  um   objeto,  mas  é  preferível  usar  alloc/init,  especialmente  se  você  pretende  ter  várias   formas  de  inicializar  o  seu  objeto.   Ótimo,  você  diz,  mas  o  que  diabos  são  aqueles  pares  de  colchetes  (“[]”)?   Seguindo  a  tradição  de  Smalltalk,  em  Objective-­‐C  a  ideia  não  é  que  você  está   chamando  um  método  em  um  objeto,  mas  sim  enviando  uma  mensagem  a  ele.   Inicialmente,  a  sintaxe  pode  realmente  parecer  um  pouco  estranha,  mas  no  fim   das  contas  ela  é  bem  simples:   [  objetoDestino  mensagem  ]   Do  lado  esquerdo,  você  sempre  tem  o  objeto  para  o  qual  você  quer  enviar  a   mensagem,  do  lado  direito  você  tem  a  mensagem  que  está  sendo  enviada  (o   método  que  está  sendo  chamado),  tudo  isso  dentro  de  colchetes.  No  nosso  caso,   onde  fazemos  “[[Conta alloc] init]”,  estamos  enviando  a  mensagem  “alloc”   para  o  objeto  que  representa  a  classe  “Conta”  e  no  valor  que  é  retornado  por  esse   método  (um  objeto  Conta)  fazemos  a  chamada  do  método  “init”.  O  idioma   alloc/init  é  comum  e  pervasivo  em  toda  a  linguagem  e  exemplos  de  código  que   você  vai  encontrar,  mas  evite  fazer  chamadas  de  método  dentro  de  chamadas  de   método  no  seu  código,  a  não  ser  que  seja  um  caso  muito  simples  como  esse  que   nós  estamos  vendo  aqui.   Na  segunda  linha  do  teste  vemos  o  seguinte:   [conta depositar:200]; Nós  enviamos  a  mensagem  “depositar”  para  o  objeto  representado  pela  variável   “conta”  com  o  parâmetro  200.  Os  “:”  que  nós  usamos  na  definição  do  método   “depositar”  fazem  realmente  parte  do  nome  do  método,  sendo  obrigatório  a  sua   adição  a  chamada  (os  métodos  que  não  adicionam  “:”  são  os  que  não  recebem   parâmetros).   No  fim  temos  o  código  que  faz  a  asserção  do  teste:   STAssertTrue( [conta saldo] == 300, @"O saldo deve ser de 300 para que o teste falhe" ); Comparamos  então  o  valor  do  saldo  com  300  exatamente  porque  queremos,   nesse  primeiro  momento,  ver  o  teste  falhar.  STAssertTrue  não  é  um  método,  mas   uma  função  comum  que  você  definiria  como  uma  função  em  C,  ela  faz  parte  do   framework  de  testes  unitários  que  vem  por  padrão  dentro  do  Cocoa.   Agora  um  detalhe  importante  que  pode  passar  desapercebido  é  a  definição  do   texto  usado  como  mensagem  para  esse  teste,  em  vez  de  ser  somente  um  conjunto   de  caracteres  entre  aspas,  há  um  “@”  antes  das  aspas.  Isso  quer  dizer  que  você  
  • 16. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       16   não  está  usando  uma  string  comum  do  C,  que  é  um  array  de  caracteres,  e  sim  um   objeto  do  tipo  NSString  que  adiciona  várias  funcionalidades  as  strings  comuns  do   C.  A  maior  parte  do  código  em  Objective-­‐C  que  lida  com  Strings  vai  esperar  que   você  envie  objetos  do  tipo  NSString,  então  é  bom  se  acostumar  a  escrever   primeiro  a  “@”  antes  de  declarar  um  string  no  seu  código.   Voltemos  agora  para  o  Xcode,  onde  você  vai  mudar  o  Target  padrão  para  Test,   veja  como  fazer  isso  na  imagem  abaixo:   Imagem  12  –  Alterando  o  Target  padrão  para  Test     Agora  estamos  entrando  no  modo  de  testes  do  Xcode  vamos  poder  começar  a   executar  os  testes,  mas  antes  de  fazer  isso  precisamos  dizer  para  o  Target  “Test”   onde  ele  vai  achar  a  classe  Conta,  pois  ela  não  foi  adicionada  a  ele.  Pra  fazer  isso,   você  deve  selecionar  o  arquivo  “Conta.m”  e  arrastá-­‐lo  para  dentro  da  pasta   “Compile  Sources”  do  Target  “Test”,  como  na  imagem  abaixo:   Imagem  13  –  Drag  e  drop  do  arquivo  “Conta.m”  em  Test    
  • 17. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       17   Com  isso  feito,  podemos  finalmente  executar  o  build  do  projeto,  pra  fazer  isso   digite  “Command  +  B”.  Após  alguns  instantes  o  Xcode  deve  terminar  de  fazer  o   build  e  você  deve  ver  um  aviso  no  canto  inferior  direito  da  ferramenta  indicando   que  existem  dois  erros:   Imagem  14  –  Indicação  de  erros  de  build  do  Xcode     Ao  clicar  nos  erros  você  deve  ver  a  seguinte  tela:  
  • 18. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       18   Imagem  15  –  tela  de  erros  no  build  do  Xcode     Como  você  pode  perceber,  o  erro  na  verdade  não  é  exatamente  no  build,  mas  sim   no  nosso  teste  unitário  que  falhou,  já  que  o  valor  da  variável  não  é  300  e  sim  200.   Para  ver  essa  tela  sem  ter  que  usar  o  mouse  pra  clicar  no  erro  basta  fazer  “Shift  +   Command  +  B”.  Agora  que  você  já  viu  a  tela,  troque  o  300  por  200  e  execute  o   build  mais  uma  vez  com  “Command  +  B”,  o  seu  build  deve  executar  sem  erros,   agora  que  o  teste  já  está  implementado  corretamente.   Vamos  agora  definir  os  métodos  sacar  e  transferir  na  classe  conta:   Listagem  6  –  Conta.h   #import <Cocoa/Cocoa.h> @interface Conta : NSObject { float saldo; } - (BOOL) depositar: (float) valor; - (BOOL) sacar: (float) valor; - (BOOL) transferir: (float) valor para: (Conta *) destino; - (float) saldo; @end Estamos  quase  chegando  lá,  o  método  sacar  tem  a  definição  igual  a  depositar,   mas  o  método  “transferir:para:”  (veja  só  como  ele  se  chama)  deve  estar  dando   um  nó  no  seu  cérebro  nesse  momento.  Vejamos:   - (BOOL) transferir: (float) valor para: (Conta *) destino; Em  Objective-­‐C,  quando  você  tem  um  método  que  recebe  vários  parâmetros,   você  precisa  “dividir”  o  nome  do  método  em  pedaços  para  receber  os  
  • 19. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       19   parâmetros.  Então  em  vez  de  simplesmente  fazer  um  “transferir(  double  valor,   Conta  destino  )”,  como  você  faria  em  Java  ou  C#,  você  quebra  o  nome  do  método   e  transformar  ele  em  “transferir:  valor  para:  destino”.     Inicialmente  a  sintaxe  parece  estranha,  mas  a  própria  leitura  da  chamada  do   método  fica  mais  simples  e  se  você  tiver  um  método  que  recebe  vários   parâmetros  ele  com  certeza  vai  ficar  bem  mais  legível,  já  que  cada  parâmetro  vai   ter  o  seu  identificador  antes.     Vejamos  agora  como  fica  a  implementação  desses  dois  métodos:   Listagem  7  –  Conta.m   #import "Conta.h" @implementation Conta - (BOOL) depositar: (float) valor { if ( valor > 0 ) { saldo += valor; return YES; } else { return NO; } } - (BOOL) sacar:(float)valor { if ( valor > 0 && valor <= saldo) { saldo -= valor; return YES; } else { return NO: } } - (BOOL) transferir:(float) valor para:(Conta *) destino { if ( [self sacar: valor] && [ destino depositar: valor ] ){ return YES; } else { return NO; } } - (float) saldo { return saldo; } @end A  essa  altura  do  campeonato,  você  já  sabe  exatamente  o  que  esse  código  todo   está  fazendo,  então  vamos  passar  diretamente  pros  testes,  pra  ver  esses  novos  
  • 20. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       20   métodos  sendo  exercitados.  Em  todos  os  nossos  testes  vamos,  utilizar  um  objeto   conta,  então  em  vez  de  recriar  esse  objeto  a  cada  teste,  vamos  ser  inteligentes   definir  uma  variável  de  instância  Conta  no  nosso  teste  e  implementar  o  método   “setUp”  que  cria  a  conta  para  não  repetirmos  essa  operação:   Listagem  8  –  ContaTest.h   #import <SenTestingKit/SenTestingKit.h> @class Conta; @interface ContaTest : SenTestCase { Conta * conta; } @end Adicionamos  a  definição  da  variável  de  instância  na  classe,  como  esperado,  mas  o   que  é  esse  “@class”  que  também  está  aí?  O  @class  em  Objective-­‐C  é  uma   “forward  reference”  e  normalmente  é  utilizado  em  arquivos  “.h”  para  que  você   diga  que  o  seu  arquivo  depende  de  uma  classe  em  específico,  mas  não  vai  fazer  o   “#import”  dessa  classe  aqui,  vai  deixar  pra  importar  o  arquivo  da  classe  somente   no  seu  “.m”.  Se  você  não  colocar  o  @class  nem  o  “#import”  pra  o  arquivo  da   classe  não  vai  ser  possível  compilar  o  código.   Um  detalhe  importante  do  “#import”  é  que  quando  o  texto  que  vem  após  ele  está   entre  “<>”  (como  em  #import <SenTestingKit/SenTestingKit.h>),  isso   indica  ao  compilador  que  ele  deve  procurar  esse  arquivo  no  “load  path”  do   sistema  operacional,  os  lugares  onde  ficam  os  arquivos  “.h”  do  mesmo.  Quando  o   “#import”  aparece  usando  aspas  no  conteúdo  a  ser  importado,  quer  dizer  que  ele   deve  procurar  dentro  dos  arquivos  locais  do  projeto  (como  em  #import "Conta.h").   Vejamos  agora  a  implementação  atual  dos  testes:   Listagem    9  –  ContaTest.m   #import "ContaTest.h" #import "Conta.h" @implementation ContaTest - (void) setUp { conta = [[Conta alloc] init]; [conta depositar: 200]; } - (void) testDepositarComSucesso { [conta depositar:150]; STAssertTrue( conta.saldo == 350, @"Saldo final deve ser 350" );
  • 21. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       21   } - (void) testDepositarComFalha { [conta depositar:-150]; STAssertTrue( conta.saldo == 200, @"Valor do saldo não deve ter se modificado" ); } - (void) testSacarComSucesso { [conta sacar:150]; STAssertTrue( conta.saldo == 50, @"O saldo atual deve ser 50" ); } - (void) testSacarComValorMaior { [conta sacar: 250]; STAssertTrue( conta.saldo == 200, @"O saldo atual não deve ter se modificado" ); } - (void) testSacarComValorNegativo { [conta sacar: -100]; STAssertTrue( conta.saldo == 200, @"O saldo atual não deve ter se modificado" ); } - (void) testTransferirComSucesso { Conta * destino = [[Conta alloc] init]; [conta transferir:150 para: destino]; STAssertTrue( conta.saldo == 50, @"O saldo da conta origem deve ser 50" ); STAssertTrue( destino.saldo == 150, @"O saldo da conta destino deve ser 250" ); } - (void) testTransferirComFalha { Conta * destino = [[Conta alloc] init]; [ conta transferir:250 para: destino ]; STAssertTrue( conta.saldo == 200, @"O saldo da conta origem deve ser 50" ); STAssertTrue( destino.saldo == 0, @"O saldo da conta destino deve ser 250" );
  • 22. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       22   } @end Temos  então  vários  testes  para  a  implementação  das  funcionalidades  da  nossa   classe  conta,  eles  são  bem  simples,  mas  tem  duas  coisas  importantes  que  não   discutimos  ainda,  a  primeira  é  essa:   conta.saldo == 200 Antes,  no  nosso  teste,  fazíamos  a  chamada  assim:   [conta saldo] == 200 Em  Objective-­‐C,  se  você  tem  um  método  que  não  recebe  parâmetros  e  retorna   um  valor,  esse  método  pode  ser  chamado  como  se  ele  fosse  uma  propriedade  do   seu  objeto,  sem  que  você  tenha  que  fazer  uma  invocação  explícita  do  mesmo,   então  “conta.saldo”  é  a  mesma  coisa  que  escrever  “[conta  saldo]”,  o  compilador   vai  fazer  a  mágica  de  transformar  o  primeiro  no  segundo  pra  você.   Já  o  segundo  caso:   [ conta transferir:250 para: destino ] Aqui  nós  vemos  um  exemplo  da  chamada  do  método  “transferir:para:”,  junto   com  o  transferir  nós  temos  o  valor  que  vai  ser  transferido  e  logo  depois  de  para   temos  o  objeto  que  vai  receber  a  transferência,  veja  que  não  existem  vírgulas   separando  os  parâmetros,  eles  são  separados  normalmente  pelos  espaços  entre   os  nomes  que  formam  o  método  e  os  parâmetros  passados.   Criando  um  “construtor”  para  o  nosso  objeto  conta   Como  já  comentamos  antes,  o  par  “[[Conta  alloc]  init]”  serve  pra  criar  o  objeto  e   inicializá-­‐lo  dentro  do  projeto,  mas  e  se  nós  quisermos  definir  uma  forma   personalizada?  Simples,  criamos  um  método  de  inicialização.  No  nosso  caso   queremos  poder  criar  contas  com  um  saldo  que  seja  diferente  de  zero.   Começamos  por  definir  o  método  “initWithSaldo”  em  “Conta.h”:   Listagem  10  –  Conta.h  –  declarando  o  método  initWithSaldo   #import <Cocoa/Cocoa.h> @interface Conta : NSObject { float saldo; } - (Conta *) initWithSaldo: (float) valor; - (BOOL) depositar: (float) valor; - (BOOL) sacar: (float) valor; - (BOOL) transferir: (float) valor para: (Conta *) destino; - (float) saldo; @end
  • 23. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       23   Como  não  existem  construtores  realmente  dentro  da  linguagem,  o  que  nós   fazemos  é  definir  métodos  que  inicializem  o  objeto  com  o  valor  que  nos   interessa,  vejamos  a  implementação  agora  pra  entender  um  pouco  mais  o  que   está  acontecendo  e  porque  é  necessário  criar  esses  métodos:   Listagem  11  –  Conta.m     #import "Conta.h" @implementation Conta - (Conta *) initWithSaldo:(float)valor { if ( self = [ self init]) { saldo = valor; } return self; } // todo aquele código que você já viu @end Mais  um  caso  de  idioma  da  linguagem  surge  então  pra  nós  nesse  momento:   if ( self = [ self init]) { Por  mais  estranho  que  pareça,  esse  código  está  realmente  atribuindo  um  valor  a   variável  “self”  (“self”  é  equivalente  ao  “this”  em  Java  e  C#,  é  uma  referência  para   o  objeto  onde  o  método  em  execução  atual  foi  chamado)  dentro  do  seu  objeto.     Mas  porque  alguém  iria  querer  fazer  isso?   Na  implementação  da  Apple  do  Objective-­‐C  existe  um  conceito  chamado  de   “class-­‐clusters”.  Quando  você  cria  um  objeto  do  tipo  NSString,  o  que  você  recebe   pode  não  ser  exatamente  um  NSString,  mas  uma  subclasse  dele.  As  classes  que   nós  vemos  “do  lado  de  fora”  funcionam  apenas  como  um  meio  pra  se  acessar  as   classes  que  fazem  realmente  o  trabalho,  mas  esses  detalhes  de  implementação   ficam  escondidos  graças  a  essa  pequena  mágica  do  método  init  (atribuir  um  novo   valor  a  self  e  retornar  esse  valor).   No  caso  da  nossa  classe  não  seria  necessário  fazer  essa  mágica,  já  que  estamos   realmente  retornando  uma  conta,  mas  o  ideal  é  que  você  construa  todos  os  seus   inicializadores  dessa  forma  para  que  quando  for  criar  uma  subclasse  de  uma   classe  padrão  da  linguagem  não  se  esquecer  e  terminar  com  bugs  estranhos  no   seu  código.   Outra  coisa  importante  também  é  lembrar-­‐se  de  chamar  o  método  “init”  da  sua   classe,  se  você  estiver  implementando  um  novo  inicializador  (como  nós  fazemos   nesse  código)  ou  chamar  o  método  init  da  sua  superclasse  (com  [super  init])  se   você  estiver  sobrescrevendo  o  método  “init”,  assim  você  não  perde  o  código  de   inicialização  que  já  tenha  sido  implementado  na  classe  atual  e  nas  suas   superclasses.   Definindo  propriedades  automaticamente  nos  objetos   Nós  vimos  que  o  compilador  é  inteligente  o  suficiente  pra  aceitar  que  “[conta   saldo]”  seja  chamado  como  “conta.saldo”,  mas  além  disso  nós  também  podemos  
  • 24. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       24   instruir  o  compilador  para  que  ele  gere  os  métodos  de  acesso  para  as   propriedades  dos  nossos  objetos  automaticamente  (pense  no  “generate  getters   and  setters”  do  Eclipse  ou  attr_accessor  em  Ruby).  Pra  isso,  vamos  definir  novas   propriedades  na  nossa  classe,  “agencia”  e    “conta”.  Vejamos  como  fica  o  nosso   “Conta.h”  agora:   Listagem  12  –  Conta.h  com  as  novas  propriedades  definidas   #import <Cocoa/Cocoa.h> @interface Conta : NSObject { float saldo; NSString * conta; NSString * agencia; } @property (copy, nonatomic) NSString * conta; @property (copy, nonatomic) NSString * agencia; @property (readonly) float saldo; - (Conta *) initWithSaldo: (float) valor; - (BOOL) depositar: (float) valor; - (BOOL) sacar: (float) valor; - (BOOL) transferir: (float) valor para: (Conta *) destino; @end Nós  definimos  as  duas  variáveis  de  instância,  “agencia”  e  “conta”,  e  logo  depois   temos  as  declarações  das  propriedades,  com  “@property”:   @property (copy, nonatomic) NSString * conta; Isso  indica  ao  compilador  que  nós  vamos  ter  os  métodos  abaixo  definidos:   -­‐ (NSString  *  )  conta;   -­‐ (void)  setConta:  (  NSString  *  );   As  instruções  “copy”  e  “nonatomic”  são  atributos  que  vão  ser  utilizados  na   geração  da  implementação  dos  métodos.     -­‐ “copy”  indica  que  quando  um  objeto  for  recebido  como  parâmetro,  deve   ser  criada  uma  cópia  desse  objeto  e  essa  cópia  é  quem  vai  ser  atribuída  a   variável  de  instância,  isso  é  necessário  especialmente  se  você  está   recebendo  dados  da  interface,  pois  os  strings  que  vem  dela  podem  ser   recolhidos  da  memória  a  qualquer  momento  nos  ambientes  onde  não  há   coletor  de  lixo,  como  iPads  e  iPhones.   -­‐ “nonatomic”  indica  que  os  métodos  gerados  não  vão  fazer  nenhum   controle  sobre  o  acesso  de  forma  concorrente.  Esse  normalmente  é  o  caso   pra  maior  parte  das  aplicações,  mas  se  você  vai  utilizar  esse  objeto  em  um   ambiente  com  concorrência,  onde  várias  threads  vão  acessar  o  mesmo   objeto  e  chamar  seus  métodos,  deve  remover  isso.   -­‐ “readonly”  indica  que  apenas  o  método  “getter”,  que  lê  o  valor  da  variável,   vai  ser  gerado,  o  método  set,  que  altera  o  valor  da  variável  não  vai  ser   gerado.  
  • 25. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       25   Com  os  métodos  definidos,  agora  voltamos  pra  “Conta.m”  pra  declarar  o  código   que  vai  fazer  com  que  os  métodos  sejam  realmente  gerados,  vejamos  como  fica  o   código  agora:   Listagem  13  –  Conta.m  com  a  definição  das  propriedades  e  gerenciamento  de   memória   #import "Conta.h" @implementation Conta @synthesize agencia, conta, saldo; - (void) dealloc { [ self.agencia release ]; [ self.conta release ]; [ super dealloc ]; } // todo o resto do código que você já conhece aqui @end A  mágica  de  verdade  vive  no  “@synthesize”,  ele  instrui  o  compilador  a  ler  as   informações  das  propriedades  definidas  através  de  “@property”  e  gerar  os   métodos.  Junto  com  isso  chegamos  a  um  detalhe  importante  da  programação   com  Objective-­‐C,  especialmente  se  você  estiver  planejando  programar  para  iOS,  o   gerenciamento  de  memória.   Com  a  definição  das  propriedades  nós  definimos  também  o  método  “dealloc”  que   é  chamado  quando  um  objeto  vai  ser  removido  da  memória,  para  que  ele  possa   limpar  da  memória  também  os  objetos  para  os  quais  ele  aponta.  Quando  você   está  programando  em  Objective-­‐C  para  iOS,  não  existe  um  coletor  de  lixo   automático,  liberar  a  memória  é  responsabilidade  do  programador,  então  é   necessário  que  você  tome  cuidado  para  não  vazar  memória  no  seu  código  e   estourar  a  memória  do  dispositivo.   Em  Objective-­‐C  o  controle  de  memória,  quando  não  é  feito  através  do  coletor  de   lixo,  acontece  através  da  contagem  de  referencias.  Sempre  que  você  cria  um   objeto  usando  “alloc”  ou  “new”  esse  objeto  fica  com  o  contador  de  referencias  em   1  (um),  cada  vez  que  você  chama  “retain”  no  objeto  (como  em  “[objeto  retain]”)   esse  contador  aumenta  em  um  e  cada  vês  que  você  chama  “release”  (como  em   “[objeto  release]”)  o  contador  diminui  em  1.  Quando  o  contador  de  referencias   atingir  0,  o  objeto  é  removido  da  memória.   No  nosso  caso,  as  propriedades  “conta”  e  “agencia”  são  definidas  como  “copy”,   isso  quer  dizer  que  o  objeto  que  vai  ser  colocado  na  variável  de  instância  vai  ser   clonado  e  o  clone  é  o  objeto  que  vai  finalmente  ficar  disponível  para  a  nossa   classe.  Como  o  clone  é  um  objeto  recém-­‐criado  com  base  em  outro  objeto  a  sua   contagem  de  referencias  é  1  (um),  o  que  quer  dizer  que  quando  chamarmos   “release”  neles,  eles  vão  ser  removidos  da  memória.   Pra  limpar  a  memória  que  estamos  usando,  precisamos  ajustar  o  nosso  teste   para  fazer  o  “release”  dos  objetos  conta  que  estão  sendo  criados.  Vamos  fazer  o  
  • 26. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       26   release  da  variável  de  instância  conta  no  método  tearDown  e  da  conta  destino   em  cada  um  dos  testes,  vejamos  o  que  muda  na  nossa  classe  teste:   Listagem  14  –  ContaTest.m  com  o  código  de  gerenciamento  de  memória   @implementation ContaTest //métodos não mostrados aqui não foram alterados - (void) tearDown { [ conta release ]; } - (void) testTransferirComSucesso { Conta * destino = [[Conta alloc] initWithSaldo: 100 ]; [conta transferir:150 para: destino]; STAssertTrue( conta.saldo == 50, @"O saldo da conta origem deve ser 50" ); STAssertTrue( destino.saldo == 250, @"O saldo da conta destino deve ser 250" ); [ destino release ]; } - (void) testTransferirComFalha { Conta * destino = [[Conta alloc] init]; [ conta transferir:250 para: destino ]; STAssertTrue( conta.saldo == 200, @"O saldo da conta origem deve ser 50" ); STAssertTrue( destino.saldo == 0, @"O saldo da conta destino deve ser 250" ); [ destino release ]; } - (void) testSetContaEAgencia { conta.agencia = @"1111-0"; conta.conta = @"10.000-9"; STAssertEqualObjects( conta.agencia, @"1111-0", @"O valor deve ser igual" ); STAssertEqualObjects( conta.conta, @"10.000-9", @"O valor deve ser igual" ); } @end
  • 27. Curso  de  desenvolvimento  de  aplicações  para  iOS  usando  Objective-­‐C   Maurício  Linhares       27   Adicionamos  a  nossa  implementação  o  método  “tearDown”  que  envia  um   “release”  para  o  objeto  conta  e  também  fazemos  o  release  dos  objetos  destino   criados  nos  testes  de  transferência.  Você  nunca  deve  chamar  o  método  dealloc   diretamente  nos  seus  objetos,  sempre  chame  release  e  deixe  que  o  próprio   runtime  do  Objective-­‐C  vai  fazer  a  chamada  a  dealloc  quando  for  a  hora  correta.   É  possível  definir  algumas  regrinhas  básicas  na  hora  de  lidar  com  a  gerência  de   memória  em  aplicações  escritas  em  Objective-­‐C:   • Se  você  pegou  um  objeto  através  de  “alloc/new/copy”,  esse  objeto  tem   um  contador  de  1  e  você  deve  se  lembrar  de  liberar  esse  objeto  quando   ele  não  for  mais  necessário;   • Se  você  pegou  um  objeto  de  outro  lugar,  assuma  que  ele  tem  um  contador   de  1,  se  você  só  vai  usá-­‐lo  e  deixar  ele  pra  lá,  não  faça  nada  com  ele,  quem   passou  ele  pra  você  provavelmente  vai  limpá-­‐lo  quando  for  necessário.     • Se  você  precisa  manter  um  objeto  recebido  de  outro  lugar  para  usá-­‐lo  em   outro  momento,  chame  “retain”  nele  para  que  o  contador  aumente  para   “2”,  assim  quando  quem  lhe  passou  esse  objeto  chamar  “release”  nele  o   contador  vai  baixar  pra  “1”  e  o  objeto  ainda  não  vai  ser  liberado  da   memória.     • Sempre  que  você  dá  “retain”  em  um  objeto,  deve  garantir  que  vai  dar  um   “release”  nele  em  algum  momento,  se  você  não  der  o  “release”,  com   certeza  vai  estar  vazando  memória  na  sua  aplicação;   Gerenciamento  de  memória  é  um  tópico  longo  e  vamos  nos  aprofundar  mais  nele   conforme  avançamos  para  a  construção  das  nossas  aplicações  para  iOS,  essa   introdução  é  apenas  para  que  você  entenda  o  básico  de  como  esse  conceito   funciona  dentro  da  linguagem.