Objota O mundo orientado a objetos

Classe com o Design Pattern Singleton no Objective-C

Posted on setembro 13, 2012

Posted by Pedro

Galera segue ai um exemplo simples para quem tem dúvidas de como criar uma classe no Design Pattern Singleton utilizando Objective-C.


//arquivo Exemplo.h

@interface Exemplo : NSObject {
    
    NSInteger propriedade;
    
}

@property(nonatomic, assign) NSInteger propriedade;

+ (Exemplo *)shared;

@end

Abaixo o código do arquivo Exemplo.m


//arquivo Exemplo.m

#import "Exemplo.h"

static Exemplo *_shared = nil;

@implementation Exemplo

@synthesize propriedade;

+ (Exemplo *)shared {
    
	if(_shared == nil){
		
		@synchronized([Exemplo class]){
			_shared = [[Exemplo alloc] init];
		}
		
	}
	
	return _shared;
	
}

- (id)init{
    
    self = [super init];
    
    if (self) {
        propriedade = 10;
    }
    
    return self;
    
}

@end


//Chamando o objeto estático

[Exemplo shared].propriedade = 20;

Espero que seja útil pra vocês. Até a próxima!

Delegate Objective-C de uma forma simples e direta

Posted on janeiro 10, 2011

Posted by Pedro

Bom, o que quero apresentar para vocês nesse POST é como utilizar delegate de uma forma direta. Haa mas como seria isso? Simples, vou apresentar um exemplo prático. Então mão na massa!

Bom primeiramente vou colocar aqui para vocês um problema simples, imagine as Classes A, B, C e D.
Nesse contexto as classes B, C e D possuem uma instancia da classe A, e dentro da classe A possui um "evento" de Print, que irá imprimir na tela uma String, porém antes de ser impresso esse texto eu tenho que avisar as classes que implementarão A que eu irei realizar essa ação, mas eu não conheço as classes que estão esperando receber esse "evento", então como resolver esse problema?

Então é ai que entra os delegates, que para quem já programa em JAVA vai entender que não passa de um tipo de Listener usado de uma forma diferente.

A criação de um delegate é realizado através da declaração @protocol no arquivo .h onde também é declarada a Classe.

Então vamos ao exemplo. Primeiramente crie um projeto View-based Application no seu Xcode com o nome de TesteDelegate.

Após criar o projeto vamos criar as classes A, B e C dentro da pasta Classes, clicando com o botão direito encima dela e escolhendo a opção Add -> New File. Feito isso vamos criar um método na classe A ( arquivo A.h ) chamado printString.

E dentro desse arquivo, vamos criar também o protocolo da nossa classe da forma apresentada abaixo, depois irei explicar o que faz cada comando.

//A.h
#import <Foundation/Foundation.h>

@protocol ADelegate <NSObject>

@required
- (void)didPrint;

@optional
- (void)willPrint;

@end

@interface A : NSObject {

	id <ADelegate>delegate;

}

@property(nonatomic, retain) id <ADelegate>delegate;

- (void)printString;

@end

//A.m
#import "A.h"

@implementation A

@synthesize delegate;

- (void)printString {

	if ([delegate respondsToSelector:@selector(willPrint)]) {
		[delegate willPrint];
	}

	NSLog(@"Escreveu a String");

	[delegate didPrint];

}

- (id) init {

	self = [super init];

	if (self != nil) {
		delegate = nil;
	}

	return self;

}

@end

Na classe A nós criamos um protocolo chamado ADelegate, esse protocolo é o delegate em si, e como vocês podem ver na declaração nós tipamos o Protocolo como NSObject para dessa forma usar os métodos da classe NSObject.

Embaixo vocês irão encontrar os métodos didPrint com o indicador @required (que serve apenas para informar que o método é de obrigatória implementação pela classe que será responsável pelo delegate) e willPrint com o indicador @optional (serve para indicar que o método não precisar ser implementado, é opcional).

Agora na @interface da classe A declaramos a variavel delegate do tipo id (tipo de dado genérico no Objective-c). Essa variável irá receber a classe que será responsável pelo delegate. Logo embaixo declaramos a propriedade (prometo que irei fazer um post sobre propriedades no objective-c) para o delegate e dessa forma conseguir enxergar essa variável a partir de outras classes.

Feito isso implementamos o método printString, Nesse método temos algumas coisas importantes para falar.

if ([delegate respondsToSelector:@selector(willPrint)]) {
     [delegate willPrint];
}

Nesse if eu verifico se o objeto delegate (que eu não sei de onde vem e quem é, só sei que deriva do NSObject, por esse motivo eu tipei esse protocolo como NSObject) responde ao método willPrint, essa verificação básicamente "olha" se a classe possui esse método implementado, se sim, eu acho o método, se não ele passa direto.

Essa é a forma que posso tornar meu método de implementação opcional.

Já na linha:

[delegate didPrint];

Caso não esteja implementado o método na classe que está setada como delegate irá gerar um erro na execução do programa.

Dessa forma eu torno o método de implementação obrigatória.

Classe B:

Na classe B é criado uma instância da classe A e setado o delegate da classe A como self (self é o mesmo que this usado nas linguagens como java, php, javascript, etc) para que a classe B seja responsável por receber os eventos (ou mensagens) enviados da classe A.

O mesmo é criado na classe C.

//B.h
#import <Foundation/Foundation.h>
#import "A.h"

@interface B : NSObject <ADelegate> {

}

@end

//B.m
#import "B.h"

@implementation B

- (id) init {

	self = [super init];

	if (self != nil) {

		A *a = [[A alloc] init];
		a.delegate = self;
		[a printString];

	}

	return self;

}

- (void)willPrint {
	NSLog(@"vai printar na classe B");
}

- (void)didPrint {
	NSLog(@"terminou de printar na classe B");
}

@end
//C.h
#import <Foundation/Foundation.h>
#import "A.h"

@interface C : NSObject <ADelegate> {

}

@end

//C.m
#import "C.h"

@implementation C

- (id) init {

	self = [super init];

	if (self != nil) {

		A *a = [[A alloc] init];
		a.delegate = self;
		[a printString];

	}

	return self;

}

- (void)willPrint {
	NSLog(@"vai printar na classe C");
}

- (void)didPrint {
	NSLog(@"terminou de printar na classe C");
}

@end

Bom com as classes já criadas, vamos ao arquivo que irá iniciar o nosso teste. Procure o arquivo main.m que está dentro da pasta Other Sources e então deixe como segue abaixo.


#import <UIKit/UIKit.h>
#import "B.h"
#import "C.h"

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

	[[B alloc] init];
	NSLog(@"--------------------------");
	[[C alloc] init];

    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

Para executar esse programa e ver o resultado pressione command + enter, ou vá ao menu Build -> Build and Debug. Então após o programa rodar no simulador vá em Run -> console e veja a saida do NSLog que colocamos no código.

E se voce quiser pode tirar o método willPrint e verificar o que vai ocorrer.

E ainda pode ver que vai gerar um erro caso retire o método didPrint.

E para fixar ainda mais a idéia de como funciona o delegate, retire o comando a.delegate da classe B e veja o resultado.

Bom galera, espero que tenham entendido, sei que algumas coisas ficaram faltando explicar, porém vou escrever sobre @property em outro artigo sem dúvidas, porém iria ficar confuso escrever tudo nesse.

Espero que gostem, dúvidas e sugestões postem por favor.

@property no Objective-C – Entendendo a linguagem

Posted on janeiro 6, 2011

Posted by Pedro

Salve salve galera, como prometido, estou aqui novamente para escrever mais um artigo para entender a linguagem objetive-C.

Dessa vez eu vou falar um pouco sobre as propriedades no obj-C, vou tentar explicar como funciona da forma mais simples possível. No entanto o conteúdo que vou apresentar aqui é basicamente o conteúdo que você irá encontrar no site http://developer.apple.com/devcenter/ios/index.action, porém aqui eu vou simplificar a explicação e claro, vou escrever em português. Hehehe! Então vamos lá! Vocês conhecem o conceito para uso dos gets and seters? Se não conhece leia esse artigo que está disponível no site. Se já conhece esses conceitos básicos de OO vamos continuar.

No objective-C para criar nossas propriedades temos que usar a declaração @property da seguinte maneira:

@interface Teste : NSObject {
        @private int variavel;
}
//@property(atributo1, atributo1, ...) tipo nome;
@property (readwrite, assign) int variavel;
@end

Pronto! Dessa forma podemos criar nossas propriedades e adicionar atributos de acesso as variáveis e objetos das nossas classes. Mas ainda precisamos criar nosso get e set, para isso a linguagem nos da uma forma de fazer isso de forma automatizada usando a diretiva @synthesize no nosso arquivo .m, da seguinte maneira:

@implementation Teste
//@synthesize nome_da_variavel;
// Dessa forma é criado o get e set dessa variável get =  variavel, set = setVariavel. Pronto! Muito simples.
@synthesize variavel;
@end

Bom então agora já sabemos como criar nossas propriedades e dessa forma acessar de outras classe seus valores, porém precisamos ainda descobrir como funcionam os atributos de uma propriedade. Vou deixar para vocês aqui os exemplos contidos diretamente no site da apple para fins mais didáticos. Irei explicar os principais atributos que são eles: getter, setter, readwrite, readonly, assign, retain, copy e no meu ver um dos mais importantes nonatomic.

getter=nome_do_metodo_get: Você indica o nome do método que irá retornar o valor da variável

@property(getter=getMaria) int joao;

setter=nome_do_metodo_set: Você indica o nome do método que irá atribuir valor a variável.

@property(setter=setMaria) int joao;

readwrite: Por padrão ao você criar uma propriedade ela já é setada com essa propriedade que determina que a propriedade irá ser lida e sobrescrita.

@property(readwrite) int joao;

readonly: A propriedade pode ser apenas lida e não sobrescrita.

@property(readonly) int joao;

assign: Por padrão ao você criar uma propriedade ele é do tipo assign ou em outras palavras declaração simples.

@property(assign) int joao;

retain: Quando sua propriedade é do tipo ponteiro ela geralmente(uns 95% das vezes) é assinalada como retain(+1) evitando que quando for usado o comando release(-1) na propriedade por outras classe ela não seja removida da memória e gere erros no programa. Para um melhor entendimento do funcionamento do retain você pode olhar esse artigo da apple sobre gerencimento de memória.

//Declaração
@property(retain) ClasseObjota *joao;
//O que é realizado o set da propriedade
-(void)setJoao:(ClasseObjota *)obj {
    if (joao != obj) {
        [joao release];
        joao = [obj retain];
    }
}

copy: Quando a propriedade é assinalada com copy e o valor da propriedade for setado, o compilador irá criar uma cópia do objeto, criando assim mais um objeto alocado na memória.

//Declaração
@property(copy) ClasseObjota *joao;
//O que é realizado o set da propriedade
-(void)setJoao:(ClasseObjota *)obj {
    if (joao != obj) {
        [joao release];
        joao = [obj copy];
    }
}

nonatomic: Em uma aplicação multithread uma mesma variável pode ser chamada com o get e setada ao mesmo tempo, com isso o valor retornado não é garantido, pois o valor setado pode não está 100% copiado para o bloco de memória e esse valor ja ter sido recuperado no get, então esse valor retornado será "quebrado". Usando o nonatomic evitamos isso simplesmente copiando o valor em outro bloco e "renomeando" esse bloco quando terminado de copiar esse valor.

@property(nonatomic) ClasseObjota *joao;

Bem galera, então é basicamente isso o conteúdo sobre propriedades. Espero que tenham gostado da matéria!
Favor postar as dúvidas, críticas e elogios para melhor ainda mais os POST's. Até a próxima.

Links importantes para desenvolvedores iPhone / iPad

Posted on agosto 25, 2010

Posted by Pedro

Galera para quem está com dificuldades em iniciar com o desenvolvimento para iPhone / iPad segue alguns links que jugo muito importates para iniciar essa "batalha" em busca de conhecimento que de certa forma está escasso aqui no Brasil.

Digamos que 99,9% do conteúdo está em inglês, então quem não possui uma boa leitura em inglês pode jogar no tradutor do google para ler.. hehe, mas o melhor mesmo é aproveitar a leva e estudar um pouco de inglês também.

Esses são os principais links:
http://developer.apple.com/ipad/sdk/index.html - Para quem está interessado em informações do iPad

http://guides.macrumors.com/Objective-C_Tutorial - Tutorial muito simples para quem está iniciando o estudo em objective-c.

http://www.iphonedevsdk.com/forum/tags/objective-c.html -  Aqui você vai encontrar 90% dos seus problemas já resolvidos.

http://developer.apple.com/iphone/library/navigation/index.html - Todas as informações que você precisa para iniciantes e programadores avançados na plataforma.

http://webclaudio.wordpress.com/category/desenvolvimento/iphone/ - Blog simplesmente fantástico sobre desenvolvimento para iPhone (em PT-BR).

http://www.edumobile.org/iphone/category/iphone-programming-tutorials/ - Tutoriais muito bacanas. Vale a pena conferir.

Essa página será atualizada com novas referências de links para estudos constantemente. Então deixe em seus favoritos e sempre que possível olhe para ver se possui alguma novidade.

E claro, você pode acompanhar o site do objota que sempre será atualizado com novas informações e tutoriais sobre iPhone / iPad.

Obrigado pessoal, e até a próxima!