sábado, 21 de dezembro de 2013

Methods in Objective-C

Write in english is not so good to me because my sense of humor will be lost... :)
But, when we write in english everybody believes. Then, I can put here a lot of lies and nobody will make a question.

Lets start... Today my post is about how call methods in Objective-C. The syntax is a little different from Java, that use a dot notation, like:

   myObject.myMethod(list of parameters)

In Objective-C we use [ ] (brackets) to call methods, like this:

   [myObject myMethod]

Is very common to see code with two or more brackets because we are trying to get an object and then call a method of this object. In the next code, [myObject getAnObject] returns an object, then I call otherMethod from this object:

[[myObject getAnObject] otherMethod]

Lets see an example. I modeled a SpaceCraft' class, and the code (.m and .h) is showed below:

#import <Foundation/Foundation.h>

@interface SpaceCraft : NSObject

@property double speed;


@end


#import "SpaceCraft.h"
#import "BlackHole.h"
#import "Planet.m"

@interface SpaceCraft()

@property (nonatomic, strong) BlackHole *hole;

- (void) travelTo:(Planet *)planet withSpeed:(double) speed;

@end

@implementation SpaceCraft

@synthesize speed;

- (void) travelTo:(Planet *)planet withSpeed:(double) speed
{
    
}

- (void) orbitSpaceCraft:(Planet *) planet atAltitude:(double) miles
{
    double actualSpeed = [self speed];
    Planet *saturn = [[Planet alloc] init];
    if ([[self hole] tooClose:self]) {
        [self travelTo:saturn withSpeed:actualSpeed];
    }
}


@end

In the @interface we can put private elements. I created a property called "hole" and a method travelTo:withSpeed. But, I want you to pay attention to method orbitSpaceCraft:atAltitude. Let's analyze details of this method.

The code below create a variable actualSpeed and put the value of the @property speed. How?

    double actualSpeed = [self speed];

Because [self speed] calls the method get (remember that I created this method when I wrote @synthesize speed)

To create an instance, we normally use a syntax like this:

    Planet *saturn = [[Planet allocinit];

[Planet alloc] returns an object and then we call init method to initialize. Of course, there are differents ways to create an instance, but this is the most common when we create our class. 

What are we doing in the code below?

    if ([[self holetooClose:self]) {

Well, because we are using the reserved word IF we can imagine that everything returns a boolean type. It's true! But, let's talk about it.

[self hole] called the method get and it returns a BlackHole object, then I called a method tooClose from this object. The code below shows the definition of this method in the BlackHole class:

- (BOOL) tooClose:(NSObject *) object;


Finally, in the code below I called the method travelTo:withSpeed. This syntax is closely to Java or C# way. The difference is the use of dot notation:

  [self travelTo:saturn withSpeed:actualSpeed];

However, we can use dot notation to properties in Objective-C. See the implementation of travelTo:withSpeed:

- (void) orbitSpaceCraft:(Planet *) planet atAltitude:(double) miles
{
    double actualSpeed = self.speed;
    Planet *saturn = [[Planet alloc] init];
    if ([self.hole tooClose:self]) {
        self.speed = actualSpeed * 2;
        [self travelTo:saturn withSpeed:actualSpeed];
    }

}

We can put object.property. This is very useful to write code.

If you are careful, you noted that travelTo:withSpeed has different implementations. I doubled the speed to scape from BlackHole (because i want to continue to write this blog). The question is, how can I do this without dot notation?

In the next post we'll talk about constructors (init methods).

See you soon...


sábado, 14 de dezembro de 2013

Atributos em Objective-C

Como qualquer outra linguagem com paradigma OO, o Objective-C permite a criação de atributos nas classes para que eles possam armazenar dados.

Para quem está acostumado, por exemplo, com atributos e métodos get e set da linguagem Java, o mais próximo que podemos fazer em Objective-C é o que pode ser visto abaixo.
No arquivo .h definimos o atributo numEscotilhas e os métodos get (numeroEscotilhas) e set (setNumeroEscotilhas:)

#import "Veiculo.h"
#import "Planeta.h"

@interface Nave : Veiculo

(int) numeroEscotilhas;

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km;

- (void) setNumeroEscotilhas:(int) num;
- (int) numeroEscotilhas;

@end

No arquivo .m fazemos a implementação dos métodos:

#import "Nave.h"

@interface Nave

@implementation Nave

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km {
    
}

- (void) setNumeroEscotilhas:(int) num {
    numeroEscotilhas = num;
}

- (int) numeroEscotilhas {
    return numeroEscotilhas;
}


@end

Realmente, é bastante parecido com o que fazemos em Java. Entretanto, com Objetive-C podemos fazer esse trabalho de uma forma mais simples.
Suponha que desejamos criar um atributo para a velocidade da nave. A definição ficaria da seguinte forma:

#import "Veiculo.h"
#import "Planeta.h"

@interface Nave : Veiculo

@property (nonatomic) int velocidade;

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km;


@end

Definimos uma @property e usamos (nonatomic) para especificar que o atributo não será thread-safe, que é o caso mais comum os atributos das classes. Já o arquivo .m ficará da seguinte maneira:

#import "Nave.h"

@implementation Nave

@synthesize velocidade = _velocidade;

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km {
    
}


@end

Usamos @synthesize para definir os métodos get e set "automaticamente" pelo compilador, isto é, não vamos fazer os métodos manualmente, mas eles existem e tem a seguinte forma:

#import "Nave.h"

@implementation Nave

@synthesize velocidade = _velocidade;

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km {
    
}

- (void) setVelocidade:(int)velocidade {
    _velocidade = velocidade;
}

- (int) velocidade{
    return _velocidade;
}


@end

Uma coisa que você pode estranhar é o fato de criar uma "nova" variável com underscore (_velocidade). Isto acontece para o compilador não se confundir se estamos chamando o método ou a variável (lembre que o método get tem o nome nome da property).

Nada impede, entretanto, que criemos nossa própria versão de um (ou dos dois) métodos. Imagine que não quero que a velocidade seja negativa, sendo assim, poderíamos ter uma versão assim:

#import "Nave.h"

@implementation Nave

@synthesize velocidade = _velocidade;

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km {
    
}

- (void) setVelocidade:(int)velocidade {
    if (velocidade < 0) {
        velocidade = 0;
    }
    _velocidade = velocidade;
}


@end

O método get permanece sendo gerado, mas o método set usado vai ser o que foi definido manualmente.

Vamos ficar por aqui. No próximo post mostraremos como fazer chamadas de métodos usando a linguagem Objective-C.

Até lá.

quarta-feira, 11 de dezembro de 2013

Objective-C

Vamos dividir o tópico da linguagem usada no iOS, o Objective-C, em alguns post, uma vez que aprender uma linguagem requer mais do que umas poucas horas. Na realidade, este (e os outros) tem post tem como objetivo introduzir os conceitos da linguagem. Na sua totalidade, a linguagem Objective-C e suas APIs são bastante amplas.

Mas, vamos ao que interessa.

A linguagem Objective-C é derivada do C, usa o paradigma orientado a objetos e tem algumas coisas um pouco diferentes das linguagens de programação mais difundidas como Java e C#.

As classes Java são criadas em dois tipos de arquivos diferentes: o arquivo de definição (com extensão .h) e o arquivo de implementação (com extensão .m). Suponha que queremos definir uma classe Nave (espacial) que herda de uma classe Veiculo. A declaração do arquivo .h ficaria da seguinte forma:


// precisa importar o haader da classe pai
#import "Veiculo.h"

// declaração do nome da classe e da classe pai
@interface Nave : Veiculo

// definição do cabeçalho dos métodos

@end


O arquivo .m teria a seguinte definição:

// precisa importar a classe header
#import "Nave.h"

@implementation Nave

// implementação dos métodos declarados

@end


No arquivo de implementação é possível definir métodos que serão privados. Para isto devemos criar uma declaração @interface e finalizar com @end, como no exemplo abaixo:

#import "Nave.h"

@interface Nave()

// declaração de métodos privados

@end

@implementation Nave


@end

Vejamos a figura abaixo, na qual estamos definindo o seguinte método:

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km;





Pode parecer estranho, mas o nome do método é orbitarNave:naAltitude. Como eu comentei antes, o Objective-C é bem diferente de outras linguagens, mas com o tempo acaba se acostumando. A implementação do método no arquivo .m fica da seguinte forma:

- (void) orbitarNave:(Planeta *) planeta naAltitude:(double)km {
    
    // implementação do método
    

}

Vou ficar por aqui para o post não ficar muito longo. No próximo vamos falar sobre atributos e métodos get e set.

Até a próxima!






sexta-feira, 22 de novembro de 2013

Arraste no Xcode para linkar

Para mostrar como faz a conexão entre os componentes visuais inseridos no storyboard e uma classe controller, fiz um pequeno vídeo de apenas 3 minutos para facilitar a visualização.

Inicialmente, o video mostra a criação de um novo projeto do tipo Single View, no qual o Xcode vai criar uma view e uma classe controller. O dispositivo de destino é o iPhone, mas poderia ser iPad ou universal.

Logo após, abrimos o storyboard e arrastamos um componente do tipo label e um componente do tipo Button. Depois dividimos a tela, deixando à mostra tanto o storyboard quando a classe controller. Feito isso, clica sobre o label e arrasta o mouse, segurando a tecla Control, até a classe controller. Isto faz o vínculo (outlet) do componente com a classe, bastante apenas dar um nome ao vínculo. O nome colocado no vídeo foi "label" e note no vídeo que foi criada uma @property. Após isso, temos que ir na classe .m e adicionar @synthesize label para poder criar os métodos "get" e "set" para a property criada.

Depois de vincular o componente label, o vídeo mostra o link para o componente Button. Desta vez, ao invés de criar um outlet foi criado uma Action, indicando que haverá um iteração. Isto acaba criando um método na classe controller. O nome que dei para o vínculo foi "clique". No arquivo .h ficou da seguinte forma:

- (IBAction)clique:(UIButton *)sender;

No arquivo .m ficou assim:

- (IBAction)clique:(UIButton *)sender {
    label.text = @"Olá mundo";

}


Note que o outlet "label" foi acessado dentro do método. O que mudamos nele foi o texto que vai ser exibido, que corresponde a propriedade text, mas poderíamos mudar muitas outras coisas, como cor, tamanho, posição, entre outras.

Não se preocupe ainda com a sintaxe do Objective-C. Farei alguns posts sobre ela nos próximos dias.

Até mais



quarta-feira, 20 de novembro de 2013

Iniciando com o Xcode

Antes de fazer o link entre os componentes da View com o Controller, achei importante mostrar alguns prints do Xcode, que é a IDE de desenvolvimento disponibilidade pela Apple. É free e pode ser baixada na App Store. Um pouco grande para os padrões de tamanho dos programas OSX, mas vale a pena usar.


Ao entrar no Xcode, a primeira coisa que nos deparamos é uma tela para saber que tipo de projeto estamos querendo criar. Existem vários tipos predefinidos e para quem está aprendendo, o projeto mais comum é o Single View.


Depois de escolher o tipo de projeto temos que definir alguns elementos. O mais importante é o nome do projeto e para qual tipo de dispositivo será feito o app. A figura abaixo mostra a tela de definição dos parâmetros do projeto.




Ao criar um projeto do tipo Single View, o Xcode já disponibiliza uma view e um controller para que a gente possa começar a usar. A figura abaixo mostra o elemento view (chamado de Storyboard) e as classes criadas que servirão de controller. O objective-C que é a linguagem de desenvolvimento do iOS segue a mesma linha do C, que contém uma linha para definição (header) e outra para a implementação.



Ao abrir o storyboard, teremos uma visão como a figura abaixo. Note que a view tem a visão da tela do iPhone (poderia ser do iPad caso o projeto fosse para este dispositivo) e é neste espaço que iremos colocar os componentes visuais, como labels, botões, imagens, entre outros. Na parte da direita temos o espaço para visualizar as propriedades dos componentes (parte superior) e os componentes propriamente ditos (parte inferior).



A classe do controller já vem com alguns elementos, como podemos ver na figura abaixo. Na direita temos o arquivo .h e na direta temos o arquivo .m. Veja que já temos dois métodos definidos: o viewDidLoad e o didReceiveMemoryWarning.


Voltando para a view... O Xcode, como a maioria das boas IDEs permite arrastar os componentes para distribui-los dentro da view da forma que desejar. Existem linhas guias que ajudam na disposição dos elementos, facilitando tamanhos, posições de um ou mais componentes.



Para cada componentes podemos definir suas propriedades em tempo de compilação, como pode ser visto na figura abaixo. Ao clicar no componente label, podemos definir, por exemplo, alinhamento, tamanho da fonte, cor do texto, entre várias outras propriedades. Veja que, até o momento, não tem nada muito diferentes de outros ambientes de programação.




Alguns componentes, como os botões, também definem eventos que podem ser disparados.



Nada demais... Muito fácil para quem já conhece outras IDEs. No próximo post vamos fazer o link entre os componentes definidor no Storyboard e a classe controller.

Até a próxima!





sábado, 16 de novembro de 2013

A conversa entre a View e o Controller

Conforme escrevemos no último post, o Controller pode conversar com a View sem restrições. Isto pode ser visto pela figura abaixo:


Pelo que podemos perceber, existe um componente de ligação, que no iOS é chamado de Outlet. Uma grande parte dos componentes visuais é conectado ao Controller dessa forma. Na verdade, todos os componentes que precisam de interação devem ser "lindados" dessa forma.
Imagine o seguinte: você tem um formulário para entrada de dados onde cada campo tem um label fixo. A pergunta é: preciso ligar esses labels ao Controller? Não! Eles não precisam de interação já que são fixos. Entretanto, os componentes de entrada de dados (chamados Text Field no iOS) provavelmente serão linkados, uma vez que será necessário obter o que foi digitado pelo usuário. Sendo assim, terá que ser criado um outlet para cada componente que se deseja manipular no Controller.

Outra forma de comunicação entre o Controller e a View é quando preciso que uma interação feita pelo usuário "dispare" algum evento. Isto é feito definindo ações (Action) em componentes da View e indicando qual evento (método) vai ser realizado no Controller quando a interação for feita.
Um exemplo muito comum é colocar um botão (Button no iOS) que vai chamar um método no Controller. Uma View de login é um exemplo típico. Ela vai ter um botão que vai disparar um método do Controller que vai validar o usuário e a senha que foram digitados.


Outra forma de comunicação entre o Controller e a View é quando, por exemplo, a View precisa ser sincronizada quando "algo" aconteceu, mesmo sem ter tido interação com usuário. Por exemplo, a página foi carregada. Neste caso, o iOS usa o padrão de projeto delegate para definir a comunicação. Sendo assim, métodos são criados no Controller e linkados com os eventos da View.





Exemplo de comunicação com delegate. Este código está no Controller e será disparado quando (1) a página foi carregada e (2) quando receber um aviso de pouca memória.

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

Agora que já vimos a forma de comunicação entre o Controller e a View, podemos mostrar como linkar os componentes visuais ao código. Mas isso vai ficar para o próximo post.

Até lá...



quarta-feira, 13 de novembro de 2013

O modelo MVC do iOS

O padrão de desenvolvimento do iOS é o modelo MVC (model - view - controller). Recomendo dar uma olhada mais profunda no livro padrões de projeto para um entendimento mais profundo.



Mas vamos dar uma explicada rápida sobre o funcionamento. A chave do padrão é ter uma forte definição de comunicação entre as partes. O controller (controlador) é que pode se comunicar livremente com o model (modelo) e a view (visão). A "faixa contínua" entre a view e o model indica que não é permitida a comunicação entre estas duas entidades.



Mas, quem é quem neste modelo MVC? Pensando numa aplicação típica, o que você vê (a interface) representa a view. É onde colocamos os componentes visuais, como labels, buttons, tables, etc.
O model contém as regras e os dados da aplicação. Imaginando uma aplicação como, por exemplo, o Instagram - as fotos que você tirou, os dados do seu perfil, quem você segue, entre outros, é o model da aplicação.
O controller é a entidade que tem o controle do que deve ser feito. Ele interage tanto com o model quando com a view de forma coordenar a dinâmica da aplicação. Por exemplo, um botão da view pode disparar um método do controller que vai buscar dados novos no model e vai mudar algum componente visual novamente na view. Isto acontece o tempo todo!

Quem é a view no Xcode? O Storyboard. É lá onde vamos colocar os componentes visuais.


Quem é o controller no Xcode? Quando criamos um projeto, o próprio Xcode cria uma classe Objective-C (linguagem usada no iOS) que vai ser o controller.


Quem o model no Xcode? Um projeto novo normalmente não cria um model. É possível ter um model numa única classe Objective-C ou ainda criar um Data Model, mas isso é papo para outro dia.

O importante é você saber que o model é importante e que os dados não podem ser "misturados" com o controller. Tenho visto muitos projetos que fazem isso. Tenha cuidado!

No próximo post vamos ver como são feitos os "links" entre o controller e a view, que são bem importantes para poder fazer as interações necessárias.

Até a próxima.