03 - Introdução ao Objective-C [Guia #dev iOS]

Com os conceitos básicos da linguagem C em sua memória, é hora de começar a se familirizar com o Objective-C. A diferença chave entre essas linguagens é que Objective-C é uma linguagem orientada a objeto, enquanto C é uma linguagem procedural.

Por | @jonathanlamimkt Programação
<p class="p1">Com os conceitos b&aacute;sicos da linguagem C em sua mem&oacute;ria, &eacute; hora de come&ccedil;ar a se familirizar com o Objective-C. A diferen&ccedil;a chave entre essas linguagens &eacute; que Objective-C &eacute; uma linguagem orientada a objeto, enquanto C &eacute; uma linguagem procedural. Isto significa que primeiro voc&ecirc; precisa entender os objetos e como se relacionam as classes. Outros conceitos que ser&atilde;o explorados nesse artigo s&atilde;o: objetos de mensagens, encapsulamento e heran&ccedil;a.</p> <h3><strong>As origens do Objective-C</strong></h3> <p class="p2">Objective-C e Cocoa s&atilde;o 2 componentes chaves da plataforma iOS. Apesar do fato que a plataforma iOS &eacute; relativamente jovem, Objective-C foi criada no in&iacute;cio dos anos 1980, em StepStone, por Brad Cox e Tom Love. A linguagem foi criada para combinar a robustez e agilidade da linguagem C com a eleg&acirc;ncia da linguagem Smaltalk. O Objective-C &eacute; um superconjunto rigoroso do C e, em contraste, &eacute; uma linguagem de programa&ccedil;&atilde;o de alto n&iacute;vel. A diferen&ccedil;a entre o Objective-C e o C &eacute; que o Objective-C &eacute; uma linguagem orientada a objetos enquanto o C &eacute; uma linguagem procedural.</p> <p class="p1">Como o iOS pode usar uma linguagem de programa&ccedil;&atilde;o desenvolvida nos anos 1980? Pouco depois da funda&ccedil;&atilde;o da NeXT, por Steve Jobs, o Objective-C foi licenciado para StepStone. A NeXT criou a NeXTSTEP, um kit de ferramentas de interface de usu&aacute;rio para o sistema operacional neXT, desenvolvido em Objective-C.</p> <p class="p1">Apesar do NeXTSTEP prover um kit de ferramentas revolucion&aacute;rio, o sistema operacional NeXT ganhou pouco espa&ccedil;o no mercado. Em 1996, a Apple comprou a NeXT e o NeXTSTEP foi renomeado para Cocoa. Esse &uacute;ltimo foi dominante com a introdu&ccedil;&atilde;o do OS X em Mar&ccedil;o de 2001 e depois com o lan&ccedil;amento do iPhone e do iOS.</p> <h3><strong>Programa&ccedil;&atilde;o Orientada a Objeto</strong></h3> <p class="p1">Na programa&ccedil;&atilde;o procedural, um programa consiste de uma s&eacute;ria de procedimentos e rotinas que s&atilde;o executadas para alcan&ccedil;ar um estado particular. Na programa&ccedil;&atilde;o orientada a objetos, por&eacute;m, uma cole&ccedil;&atilde;o de objetos interage e trabalham juntos para completar uma tarefa. Apesar do resultado final poder ser id&ecirc;ntico, a metodologia e os paradigmas fundamentais s&atilde;o substancialmente diferentes. Modularidade e c&oacute;digo reutiliz&aacute;vel s&atilde;o duas das principais vantagens da programa&ccedil;&atilde;o orientada a objetos, como veremos em breve.</p> <h3><strong>Objective-C, Cocoa and Cocoa Touch</strong></h3> <p class="p1">Novos desenvolvedores nos ecossistemas iOS e OS X muitas vezes se confundem com a rela&ccedil;&atilde;o entre Objective-C, Cocoa (OS X), and Cocoa-Touch (iOS). O que &eacute; Cocoa-Touch e como ele se relaciona com o Objective-C? Cocoa-Touch &eacute; uma API (application programming interface) nativa da Apple para as plataformas iOS e OSX. Objective-C &eacute; a linguagem que d&aacute; os poderes &agrave; Cocoa-Touch. Enquanto esse artigo se concentra principalmente na programa&ccedil;&atilde;o em Objective-C, em artigos futuros n&oacute;s veremos um pouco mais sobre Cocoa e Cocoa-Touch.</p> <h3><strong>Classes, Objetos e Inst&acirc;ncias</strong></h3> <p class="p1">Outro obst&aacute;culo para os desenvolvedores novos na programa&ccedil;&atilde;o orientada a objetos &eacute; distinguir entre classes, objetos e inst&acirc;ncias. Uma classe &eacute; um molde ou diagrama para a cria&ccedil;&atilde;o de objetos, enquanto inst&acirc;ncias s&atilde;o ocorr&ecirc;ncia &uacute;nicas de uma classe. Um objeto &eacute; uma estrutura de dados que tem um estado e comportamento. Apesar da s&uacute;til diferen&ccedil;a entre objetos e inst&acirc;ncias, ambos os termos s&atilde;o utilizados indistintamente &agrave;s vezes.</p> <p class="p1">Vamos ver um exemplo: torradeiras. Antes de uma torradeira ser produzida, engenheiros criam um projeto, que &eacute; o equivalente a uma classe. Cada torradeira criada a partir do projeto &eacute; uma inst&acirc;ncia ou uma &uacute;nica ocorr&ecirc;ncia do projeto. Apesar de cada torradeira ser criada a partir do mesmo projeto (classe), cada uma tem o seu estado (cor, n&uacute;mero de aberturas para os p&atilde;es, etc) e comportamento</p> <h3><strong>Vari&aacute;veis de Inst&acirc;ncia e Encapsulamento</strong></h3> <p class="p1">O estado de uma inst&acirc;ncia &eacute; armazenado e definido por suas vari&aacute;veis de inst&acirc;ncia, ou os atributos de objeto se voc&ecirc; quiser. isso nos leva a um outro padr&atilde;o chave da programa&ccedil;&atilde;o orientada a objetos: encapsulamento. Encapsulamento significa que a representa&ccedil;&atilde;o interna de objeto &eacute; privado e apenas do conhecimento do objeto em si. Isso pode parecer uma restri&ccedil;&atilde;o severa &agrave; primeira vista. Por&eacute;m, o resultado &eacute; um c&oacute;digo modular e flex&iacute;vel.</p> <p class="p1">Vamos ilustrar o encapsulamento com outro exemplo. A velocidade de um carro &eacute; medida por componentes internos, mas que estiver dirigindo o carro sabe a velocidade s&oacute; de olhar para o marcador no painel. Quem est&aacute; dirigindo n&atilde;o precisa saber ou entender como os componentes internos do carro medem a velocidade. Da mesma forma, n&atilde;o &eacute; preciso que o motorista saiba como o motor funciona para poder dirigir. Os detalhes de como o carro trabalha s&atilde;o ocultos para o piloto. O estado e comportamento do carro s&atilde;o ocultos para o piloto e acess&iacute;veis atrav&eacute;s do painel e componentes como (pedais, volante, bot&otilde;es de comando&hellip;)</p> <h3><strong>Heran&ccedil;a</strong></h3> <p class="p1">Outro paradigma forte da programa&ccedil;&atilde;o orientada a objetos &eacute; a heran&ccedil;a de classe. Quando uma classe A &eacute; uma subclasse da classe B, a classe A herda os atributos e comportamentos da classe B. A classe B &eacute; definida como classe pai ou superclasse de A. Heran&ccedil;a tamb&eacute;m promove a reusabilidade de c&oacute;digo e modularidade.</p> <h3><strong>M&eacute;todos e Propriedades</strong></h3> <p class="p1">M&eacute;todos s&atilde;o subrotinas associadas com uma classe, e que definem o comportamento da classe e das inst&acirc;ncias. Os m&eacute;todos de uma classe t&ecirc;m acesso &agrave;s inst&acirc;ncias internas e podem assim, modificar o estado da inst&acirc;ncia. Em outras palavras, o estado de uma inst&acirc;ncia &eacute; controlado pelos m&eacute;todos de uma inst&acirc;ncia.</p> <p class="p1">Devido ao padr&atilde;o de encapsulamento, as vari&aacute;veis de inst&acirc;ncia de uma classe n&atilde;o podem ser acessadas livremente. Elas s&atilde;o acessadas atrav&eacute;s de <strong>getters</strong> and <strong>setters</strong>, m&eacute;todos que permitem recuperar e passar valores a vari&aacute;veis de inst&acirc;ncia. Properiedades s&atilde;o uma caracter&iacute;stica do Objective-C, que fazem a cria&ccedil;&atilde;o dos m&eacute;todos de acesso (getters and setters). Apesar da utilidade desses m&eacute;todos, rapidamente se torna complicado escrever m&eacute;todos de acesso para cada vari&aacute;vel de inst&acirc;ncia. Mais adiante veremos outros detalhes sobre propriedades.</p> <h3><strong>Aplicando os conceitos</strong><span style="font-size: 13px;">&nbsp;</span></h3> <p class="p1">Vamos colocar em pr&aacute;tica o que foi explicado acima. Para isso, abra o Xcode e crie um novo projeto (File &gt; New &gt; Project), como mostra a figura 1. Como vimos no artigo anterior, selecione o <strong>Command Line Tool </strong>como template de projeto, que fica na categoria<strong> Application</strong>, logo abaixo de&nbsp;<strong> OS X, </strong>como mostra a figura 2.</p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img01.png" alt="" /></span></p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img02.png" alt="" /></span></p> <p class="p1">Preencha os campos conforme a tela a seguir. Para esse projeto, &eacute; importante definir o tipo como <strong>Foundation</strong>. Certifique-se tamb&eacute;m de que a op&ccedil;&atilde;o <strong>Use Automatic Reference Counting</strong> esteja marcada, e clique em <strong>Next.</strong></p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/td_img03.png" alt="" /></span></p> <p class="p1">Agora escolha o local onde vai salvar o seu projeto e clicar em <strong>Create</strong>.</p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img04.png" alt="" /></span></p> <p class="p1">Voc&ecirc; poder&aacute; observar em seguida que o projeto foi criado de forma diferente do anterior. Veremos essas diferen&ccedil;as posteriormente.</p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/td_img05.png" alt="" /></span></p> <h3><strong>Vis&atilde;o geral do projeto</strong></h3> <p class="p2">O projeto cont&eacute;m mais arquivos e pastas do que o projeto criado anteriormente. Al&eacute;m do <strong>main.m&nbsp;</strong> e <strong>Books.1</strong>, existem 2 novas pastas, <strong>Supporting Files&nbsp;</strong> and <strong>Frameworks</strong>, cada uma contendo um item.</p> <p class="p1"><strong>Supporting Files </strong>cont&eacute;m o arquivo <strong>Books-Prefix.pch</strong>. A extens&atilde;o <strong>.pch</strong> informa que este &eacute; um arquivo de cabe&ccedil;alho pr&eacute;-compilado. Mais adiante veremos seu prop&oacute;sito.</p> <p class="p2">A pasta <strong>Frameworks</strong> cont&eacute;m os frameworks que o projeto utilizar&aacute; e que forem linkados. O que um framework? &Eacute; um pacote ou diret&oacute;rio que cont&eacute;m uma biblioteca incluindos seus recursos. O conceito de arquivo de cabe&ccedil;alho ficar&aacute; claro em um minuto. A pasta bFramework<strong> cont&eacute;m um item, Foundation.framework</strong>. Quando o projeto foi criado voc&ecirc; definiu o seu tipo como <strong>Foundation</strong>, isso significa que ele est&aacute; ligado ao framework <strong>Foundation</strong>. Esse framework &eacute; um conjunto fundamental de classes do Objective-C. Veremos mais detalhes desse framework em outro artigo.</p> <h3><strong>Criando uma classe</strong></h3> <p class="p1">Chegou a hora de criarmos a primeira classe. Sempre que voc&ecirc; criar um novo arquivo (File &gt; New &gt; File&hellip;), ser&aacute; exibida uma lista de templates. Escolha <strong>Cocoa</strong> na se&ccedil;&atilde;o <strong>OS X</strong> e selecione <strong>Objective-C class</strong> como template para criar a nova classe. Clique em <strong>Next</strong> para continuar.</p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img06.png" alt="" /></span></p> <p class="p1">D&ecirc; o nome de <strong>Books</strong> para a nova classe e na subclasse escolha <strong>NSObject</strong>. Como vimos anteriormente, criando a nova classe como uma subclasse de <strong>NSObject</strong>, ela vai passar a herdar os atributos e comportamentos de <strong>NSObject.</strong> Fazendo isso, a classe <strong>Book</strong> j&aacute;inicia com as funcionalidades herdadas de <strong>NSObject.</strong></p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img07.png" alt="" /></span></p> <p class="p2"><span class="img_editor"><img src="https://www.oficinadanet.com.br/imagens/post/9954/img08.png" alt="" /></span></p> <p class="p1">Ao clicar em <strong>Create</strong>, o Xcode adiciona 2 arquivos ao projeto, <strong>Book.h</strong> and <strong>Book.m</strong>. <strong>Book.h</strong> &eacute; o arquivo de cabe&ccedil;alho da classe Book e exp&otilde;e a interface da classe. A interface da classe cont&eacute;m as propriedade e m&eacute;todos dela, e tamb&eacute;m especifica a superclasse. <strong>Book.m </strong>&eacute; o arquivo de implementa&ccedil;&atilde;o da classe e define seu comportamento para a implementa&ccedil;&atilde;o de m&eacute;todos declarados no arquivo de cabe&ccedil;alho da classe.</p> <h3><strong>Header File</strong></h3> <p class="p1">Abra o arquivo <strong>Book.h&nbsp;</strong> e d&ecirc; uma analisada no seu conte&uacute;do. Entre as linhas 1 e 7 temos os coment&aacute;rios iniciais do arquivo, e a partir da linha 9 j&aacute; temos a codifica&ccedil;&atilde;o do mesmo. A primeira linha de c&oacute;digo, linha 9,&nbsp; &eacute; o <strong>import</strong> da framework <strong>Foundation.</strong> Com esse import liberamos o acesso &agrave;s classes e protocolos declarados na framework Foundation.</p> <p class="p1"><code>#import <Foundation/Foundation.h></code></p> <p class="p1">A segunda e a terceira linha, respectivamente linhas 11 e 13 no arquivo, forma um par. Em objective-C uma classe sempre come&ccedil;a com a declara&ccedil;&atilde;o <strong>@interface</strong> e termina com <strong>@end</strong>, ambos s&atilde;o diretivas de compila&ccedil;&atilde;o, que &eacute; um comendo ou instru&ccedil;&atilde;o para o compilador. A diretiva <strong>@interface</strong> &eacute; seguida pelo nome da classe, dois pontos (:) e a superclasse (se for utilizada).&nbsp;</p> <p><code>@interface Book : NSObject<br />@end</code></p> <blockquote><strong>NSObject</strong> &eacute; a classe root da maioria das classes do Onjective-C. As primeiras duas letras, <strong>NS</strong>, fazem refer&ecirc;ncia &agrave; sua origem, NeXTSTEP, como comentado anteriormente. As classes que herdam de NSObject podem fazer uso de m&eacute;todos das rotinas b&aacute;sicas de execu&ccedil;&atilde;o.</blockquote> <p class="p1"><span style="font-weight: bold; font-size: 1.17em;">Implementation File</span></p> <p class="p1">Antes de fazermos modifica&ccedil;&otilde;es na classe Book, vamos ver um pouco sobre o arquivo de implementa&ccedil;&atilde;o <strong>Book.m</strong>. Ao inv&eacute;s de importar a framework Foundation, o arquivo de implementa&ccedil;&atilde;o importa o arquivo de cabe&ccedil;alho da classe Book (Book.h). Por que isso &eacute; necess&aacute;rio? O arquivo de implementa&ccedil;&atilde;o precisa saber que propriedades e m&eacute;todos est&atilde;o declarados no arquivo de cabe&ccedil;alho antes de poder implementar o comportamento da classe. A declara&ccedil;&atilde;o de importa&ccedil;&atilde;o &eacute; seguida pela implementa&ccedil;&atilde;o da classe, indicada por <strong>@implementation</strong> e terminada por <strong>@end</strong>.</p> <h3><strong>Adicionando propriedades e m&eacute;todos</strong></h3> <p class="p1">A classe Book n&atilde;o &eacute; muito &uacute;til na implementa&ccedil;&atilde;o atual. Volte para o arquivo de cabe&ccedil;alho e adicione 3 propriedades: <strong>year</strong>, <strong>title</strong> and <strong>author</strong>, e adicione o m&eacute;todo chamado <strong>bookInfo</strong>. Propriedades s&atilde;o declaradas com a palavra-chave <strong>@property </strong>e podem ser declaradas em qualquer lugar do bloco @interface da classe. A palavra-chave <strong>@property </strong>&eacute; seguida pelo tipo e o nome da propriedade. N&atilde;o se esque&ccedil;a do asterisco (*) na frente das propriedades <strong>title</strong> e <strong>author, </strong>porque um objecto Cocoa &eacute; sempre referenciado como um ponteiro.</p> <p class="p1">A declara&ccedil;&atilde;o do m&eacute;todo pouco se assemelha a uma fun&ccedil;&atilde;o, mas existem algumas diferen&ccedil;as essenciais. A declara&ccedil;&atilde;o do m&eacute;todo se inicia com o sinal de menos (-), indicando que esta &eacute; uma inst&acirc;ncia do m&eacute;todo. M&eacute;todos de classe s&atilde;o prefixados pelo sinal de mais (+). O sinal de menos (-) &eacute; seguido pelo tipo de dado que ser&aacute; retornado, coloca entre entre par&ecirc;nteses, como uma inst&acirc;ncia de <strong>NSString</strong>, e o nome do m&eacute;todo. O fechamento da declara&ccedil;&atilde;o do m&eacute;todo &eacute; feito com um ponto-e-v&iacute;rgula(;);</p> <p class="p1"><code>#import<br />@interface Book : NSObject<br />@property int year;<br />@property NSString *title;<br />@property NSString *author;<br />- (NSString *)bookInfo;<br />@end</code></p> <blockquote>Tenho certeza que voc&ecirc; est&aacute; se perguntando o que NSString &eacute; e porque precisa ser referenciada como um ponteiro. A classe NSString &eacute; um membro da framework Foundation. Declara a interface para um objeto que gerencia uma string imut&aacute;vel. Em artigo anterior, n&oacute;s vimos que uma string em C pode ser representada por um array de caracteres e isso &eacute; o que NSString faz exatamente, ela gerencia um array de caracteres. A vantagem de usar NSString &eacute; que o trabalho com cadeias de caracteres fica mais f&aacute;cil.</blockquote> <p class="p1">&nbsp;</p> <h3>Implementando <em>bookInfo</em></h3> <p class="p1">Agora que j&aacute; declaramos o m&eacute;todo <strong>bookInfo</strong> no arquivo de cabe&ccedil;alho, &eacute; hora de implementar no arquivo de implementa&ccedil;&atilde;o. Abra o arquivo <strong>Book.m</strong> e adicione o seguinte c&oacute;digo ap&oacute;s o bloco <strong>@implementation</strong>.</p> <p class="p1"><code>- (NSString *)bookInfo {<br />    NSString *bookInfo = [NSString stringWithFormat:@"%@ foi escrito por %@ e publicado em %i", self.title, self.author, self.year];<br />    return bookInfo;<br />}</code></p> <h3>Envio de mensagens a objetos</h3> <p class="p1">J&aacute; sabemos que o comportamento de uma classe &eacute; definido atrav&eacute;s de seus m&eacute;todos. Para chamar um m&eacute;todo em um objeto, uma mensagem &eacute; enviada para o objeto. Veja o c&oacute;digo a seguir para entender esse conceito.</p> <p class="p1"><code>NSString *string = @"Isso é uma frase.";<br />int length = [string length];<br />NSLog(@"O comprimento da frase é %i.n" length);</code></p> <p class="p1">Na primeira linha n&oacute;s declaramos uma nova string e definimos o seu valor como constante, colocando-o entre aspas duplas ("), precedido de @.&nbsp;</p> <p class="p2">Na segunda linha n&oacute;s chamamos o m&eacute;todo <strong>length</strong>, que retorna a quantidade de caracteres que a frase possui. Essa chamada de m&eacute;todo &eacute; considerada uma mensagem de objeto, pois estamos enviando uma mensagem ao objeto para obtermos um retorno. A vari&aacute;vel que receber&aacute; esse retorno foi definida com o tipo <strong>int</strong>, pois o retorno ser&aacute; um valor inteiro.</p> <p class="p2">Na &uacute;ltima linha, n&oacute;s usamos o m&eacute;todo <strong>NSLog</strong> para escrevermos na tela do console o comprimento da frase.</p> <p class="p1">O envio de mensagens a objetos &eacute; algo que ser&aacute; feito por repetidas vezes durante o desenvolvimento de aplicativos para iOS, por isso &eacute; importante entender a sintaxe. Apesar da sintaxe ser de uma forma diferenciada, se voc&ecirc; est&aacute; come&ccedil;ando a estudar o Objective-C, isso n&atilde;o vai ser t&atilde;o dif&iacute;cil de entender. Entre colchetes est&aacute; o objecto do lado esquerdo e a mensagem do lado direito.</p> <p class="p2"><code>[object message];</code></p> <p class="p1">M&eacute;todos que aceitam argumentos podem parecer um pouco diferentes, mas a sintaxe, de um modo geral, &eacute; id&ecirc;ntica. A classe NSString, por exemplo, tem outro m&eacute;todo chamado <strong>substringFromIndex:</strong>. Os dois pontos (:) no final do nome indicam que este m&eacute;todo aceita argumentos. Veja a seguir como &eacute; feita a chamada desse m&eacute;todo.</p> <p class="p2"><code>NSString *substring = [string substringFromIndex:5];</code></p> <p class="p1">Objective-C &eacute; conhecido por ter m&eacute;todos com nomes muito longos. Veja no pr&oacute;ximo exemplo um m&eacute;todo que aceita m&uacute;ltiplos argumentos. temos que admitir que por mais que o nome do m&eacute;todo seja longo, o seu comportamento fica bem claro, pois o nome diz tudo. O nome do m&eacute;todo &eacute; dividido em partes, cada parte aceitando um argumento.</p> <p class="p1"><code>NSString *anotherString = [string stringByPaddingToLength:5 withString@"outra string" startingAtIndex:2];</code></p> <p class="p1">Antes de continuarmos, n&oacute;s precisamos voltar &agrave; implementa&ccedil;&atilde;o de <strong>bookInfo</strong>. A implementa&ccedil;&atilde;o do m&eacute;todo se inicia repetindo a declara&ccedil;&atilde;o do m&eacute;todo. O ponto-e-v&iacute;rgula (;) no final &eacute; substitu&iacute;do por um par de chaves, que envolvem a implementa&ccedil;&atilde;o do m&eacute;todo. Declaramos primeiro a nova string, <strong>bookInfo</strong>,&nbsp; e apontamos para ele o seu valor, sendo esse valor criado com os atributos da inst&acirc;ncia <strong>(title, author&nbsp;</strong> e <strong>year)</strong>. No final do m&eacute;todo, n&oacute;s retornamos o valor da nova string, porque o tipo de retorno esperado para esse m&eacute;todo &eacute; &eacute; uma string.</p> <p class="p1">Tr&ecirc;s coisas exigem esclarecimentos:</p> <ol> <li>o m&eacute;todo <strong>stringWithFormat:</strong> &eacute; um m&eacute;todo de classe e n&atilde;o uma inst&acirc;ncia do m&eacute;todo. Sabemos disso porque o m&eacute;todo &eacute; chamado na sua pr&oacute;pria classe, <strong>NSString</strong>, n&atilde;o em uma inst&acirc;ncia dela. M&eacute;todos de classe s&atilde;o comuns na programa&ccedil;&atilde;o orientada a objetos.</li> <li>o formato especificado para um objeto &eacute; representado pelo s&iacute;mbolo <strong>@</strong> (precedido pelo sinal %). Tanto <strong>title</strong> quanto<strong> author</strong> s&atilde;o objetos (strings para ser preciso).</li> <li>a palavra-chave <strong>self</strong> sempre referencia a inst&acirc;ncia de classe. Nesse caso, <strong>self</strong> se refere &agrave; inst&acirc;ncia <strong>Book</strong>, na qual o m&eacute;todo <strong>bookInfo</strong> pertence.</li> </ol> <p class="p2">Se voc&ecirc; trabalhou com outras linguagens de programa&ccedil;&atilde;o orientadas a objetos, o acesso a vari&aacute;veis de inst&acirc;ncia em Objective-C pode ser um pouco confuso. N&oacute;s n&atilde;o acessamos diretamente uma vari&aacute;vel de inst&acirc;ncia quando escervemos <strong>self.title</strong>. Isso &eacute; nada mais que um atalho para <strong>[self title]</strong>. Esse &uacute;ltimo significa que n&oacute;s usamos o m&eacute;todo getter para recuperar o valor da vari&aacute;vel <strong>title</strong>. O mesmo &eacute; v&aacute;lido para definirmos um valor para a vari&aacute;vel de inst&acirc;ncia. Veja no c&oacute;digo a seguir:</p> <p><code>self.title = @"O Hobbit";<br />//equivalente<br />[self setTitle:@"O Hobbit"]</code></p> <h3><strong>id, nill e NULL</strong></h3> <p class="p2">Antes de come&ccedil;armos a usar a classe <strong>Book</strong>, eu quero falar sobre algumas palavras-chave que confundem as pessoas de vez em quando. Sempre que voc&ecirc; quer armazenar um objeto sem definir explicitamente o tipo do objeto, voc&ecirc; usa o tipo <strong>id</strong>, que &eacute; tamb&eacute;m um tipo default para retornos e declara&ccedil;&otilde;es de argumentos para m&eacute;todos em Objective-C. O poder e a utilidade do tipo <strong>id</strong> vai muito mais longe. O tipo <strong>id </strong>&eacute; um componente chave de tipagem e liga&ccedil;&atilde;o din&acirc;mica do Objective-C.</p> <p class="p2">&Eacute; importante entender que o tipo <strong>id</strong> n&atilde;o det&eacute;m&nbsp; qualquer informa&ccedil;&atilde;o sobre o objeto em si. Em Objective-C, cada objeto sabe a qual classe pertence, e isso &eacute; fundamental. Por que isso? Um dos pontos fortes do Objective-C &eacute; a tipagem din&acirc;mica, que significa que a verifica&ccedil;&atilde;o de tipo &eacute; realizada em tempo de execu&ccedil;&atilde;o, ao inv&eacute;s de ser em tempo de compila&ccedil;&atilde;o. No entanto, uma vez que o tipo de dado <strong>id</strong> n&atilde;o diz ao compilador a que classe o objeto pertence, o objeto em si precisa fornecer essa informa&ccedil;&atilde;o para o compilador.</p> <p class="p1">Isso nos leva a outro componente vital de tempo de execu&ccedil;&atilde;o no Objective-C, a liga&ccedil;&atilde;o din&acirc;mica. Em Objective-C, uma diferen&ccedil;a importante entre fun&ccedil;&otilde;es e mensagens &eacute; que a mensagem e o objeto de recep&ccedil;&atilde;o n&atilde;o est&atilde;o ligados&nbsp; at&eacute; a execu&ccedil;&atilde;o. O que isso significa e por que isso &eacute; importante? Significa que o m&eacute;todo invocado em resposta a uma mensagem enviada a um objeto &eacute; determinado no tempo de execu&ccedil;&atilde;o quando a mensagem e o objeto s&atilde;o conhecidos. isso &eacute; conhecido como liga&ccedil;&atilde;o din&acirc;mica.</p> <p class="p1">Em Objective-C, a palavra-chave <strong>nil</strong> &eacute; definida como um objeto nulo, que &eacute;, um <strong>id</strong> com valor 0 (zero). "Por baixo dos panos" isso n&atilde;o diferencia <strong>nil, Nil </strong>e <strong>NULL</strong>, e isso &eacute; poss&iacute;vel para enviar mensagens a cada um deles sem lan&ccedil;ar uma exce&ccedil;&atilde;o. A conven&ccedil;&atilde;o &eacute; para usar <strong>nil</strong> para objetos, <strong>Nil </strong>para classes, e <strong>NULL </strong>para outros casos. Ser capaz de enviar mensagens para <strong>nil</strong>, <strong>Nil</strong> e <strong>NULL </strong>tem benef&iacute;cios, mas isso tamb&eacute;m tem malef&iacute;cios.&nbsp;</p> <h3><strong>Criando Objetos</strong></h3> <p class="p1">Abra o arquivo <strong>main.m</strong> e adicione a a linha de comando para importar o arquivo de cabe&ccedil;alho da classe <strong>Book</strong>.&nbsp;</p> <h3>#import "Book.h"</h3> <p class="p1">Imediatamente depois de chamar <strong>NSLog</strong>, adicione o bloco de c&oacute;digo a seguir para criar uma inst&acirc;ncia da classe <strong>Book.</strong></p> <p class="p1"><code>Book *book1 = [[Book alloc] init];<br />book1.title = @"O Hobbit";<br />book1.author = @"JRR Tolkien";<br />book1.year = 1937;</code></p> <p class="p1">Na primeira linha declaramos uma vari&aacute;vel do tipo <strong>Book</strong> e a inicializamos. O primeiro m&eacute;todo chamado &eacute; o <strong>alloc</strong>, que aloca mem&oacute;ria para o novo objeto e o cria. Em seguida &eacute; chamado o m&eacute;todo <strong>init</strong>, que inicializa o novo objeto, para que possa ser utilizado. O m&eacute;todo <strong>init</strong> retorna a inst&acirc;ncia, e a vari&aacute;vel <strong>book1</strong> passa poder utilizar os m&eacute;todos e propriedades da classe <strong>Book</strong>. As tr&ecirc;s linhas seguintes s&atilde;o a passagem de valores para as propriedades do objeto, que j&aacute; vimos anteriormente como funcionam.</p> <p class="p1">Vamos criar agora uma nova inst&acirc;ncia da classe <strong>Book</strong>, chamada <strong>book2.</strong></p> <p class="p1"><code>Book *book2 = [[Book alloc] init];<br />book2.title = @"A Sociedade do Anel";<br />book2.author = @"JRR Tolkien";<br />book2.year = 1954;<br />NSArray *books = [[NSArray alloc] initWithObjects: book1, book2, nil];</code></p> <p class="p2">Na &uacute;ltima linha do c&oacute;digo acima n&oacute;s criamos uma inst&acirc;ncia de <strong>NSArray</strong>, outra classe da framework Foundation. A classe <strong>NSArray</strong> &eacute; um array que pode armazenar uma lista ordenada de objetos. Repare que assim como foi feito para a classe <strong>Books</strong>, tamb&eacute;m foi alocada mem&oacute;ria para a classe <strong>NSArray</strong>. A diferen&ccedil;a &eacute; que ao inv&eacute;s de apenas inicializar com <strong>init</strong>, nesse caso usamos <strong>initWithObjects: </strong>que j&aacute; inicializa a inst&acirc;ncia com os valores. &Eacute; preciso lembrar que nesses casos, o &uacute;ltimo valor informado para o argumento deve ser <strong>nil</strong>.</p> <h3><strong>Misturando C e Objective-C</strong></h3> <p class="p1">Eu tenho mencionado constantemente que Objective-C &eacute; um superconjunto estrito de C que n&oacute;s podemos combinar livremente C e Objective-C. Vamos ver como isso funciona. Come&ccedil;aremos usando um <strong>if/else</strong> para verificar a quantidade de objetos do array. Para enviar a mensagem que nos retornar&aacute; a quantidade de elementos, usamos <strong>count</strong>.</p> <p class="p1">Se o array contiver objetos, n&oacute;s executamos um loop para fazer a itera&ccedil;&atilde;o entre os objetos no array. Durante cada itera&ccedil;&atilde;o, n&oacute;s dizemos ao array que queremos o objeto na posi&ccedil;&atilde;o <strong>i</strong>, e enviamos a mensagem. Vamos obter como retorno uma string, que vamos imprimir no console atrav&eacute;s de <strong>NSLog</strong>.</p> <p class="p1"><code>if ([books count] > 0)<br />{<br />    for(int i = 0; i < [books count]; i++)<br />    {<br />        Book *aBook = [books objectAtIndex:i];<br />        NSLog(@"%@", [aBook bookInfo]);<br />    }<br />}</code></p> <p class="p1">Tenho quase certeza que voc&ecirc; est&aacute; sobrecarregado com informa&ccedil;&otilde;es sobre Objective-C. Isso &eacute; normal. Ainda veremos mais algumas informa&ccedil;&otilde;es informa&ccedil;&otilde;es sobre Objective-C nos pr&oacute;ximos artigos, antes de entrarmos de fato no desenvolvimento para iOS, usando a iOS SDK.</p> <p class="p1">Para conseguir um desempenho satisfat&oacute;rio nos estudos da iOS SDK &eacute; necess&aacute;rio dominar um pouco o Objective-C, para n&atilde;o tornar o estudo mais complicado. O caminho pode parecer longo, mas ser&aacute; prazeroso e incans&aacute;vel.</p>

Mais sobre: guiadevios objective-c programação
Share Tweet
Comentários
Carregar comentários
Destaquesver tudo

Siga nossas contas no Twitter