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

13.617 visualizações

Publicada em

Primeira versão do material do curso de desenvolvimento de aplicações para iOS usando Objective-C.

Publicada em: Tecnologia
1 comentário
9 gostaram
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
13.617
No SlideShare
0
A partir de incorporações
0
Número de incorporações
8
Ações
Compartilhamentos
0
Downloads
1.353
Comentários
1
Gostaram
9
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

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

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

×