Tratamento de Exceptions em Objective-C

A linguagem Objective-C possui uma sintaxe para tratamento de exceptions parecido com Java e C++. As exceptions podem ser do tipo NSException, NSError ou podem ser classes customizadas que são subclasses de NSException.

O suporte a exception é feito pelas diretivas de compilação: @try, @catch, @throw, e @finally. A seguir irei definir o signigicado de cada diretiva.

@try: inicia um bloco de tratamento de exception, dentro dele deve estar todo código que pode ou deve lançar alguma exception.

@catch: contém o tratamento de uma determinada exception lançada pelo código contido no bloco @try.

@throw: sua finalidade é lançar uma exception.

@finally: todo código contido neste bloco será executado independente de uma exception ser lançada ou não dentro do bloco @try.

A sintaxe comum para declar um bloco @try..@catch..@finally é:

1
2
3
4
5
6
7
8
9
@try {
  //codigo aqui
}
@catch( NSException *exception ) {
  //tratamento da exception aqui  
}
@finally {
  //codigo sempre executado aqui  
}

Agora vou criar um pequeno exemplo para demostrar o bloco funcionando. Irei criar uma instancia da classe NSObject e dentro do bloco @try irei invocar o método doNothing que não existe e com isso será lançada um NSException.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NSLog( @"Creating the instance of NSObject" );
NSObject *object = [[NSObject alloc] init];

@try {
  NSLog( @"try block" );
  [object doNothing];
}
@catch( NSException *exception ) {
  NSLog( @"catch block" );
  NSLog(@"main: Caught %@: %@", [exception name], [exception  reason]);
}
@finally {
  NSLog(@"finally block");
}

O resultado desse exemplo é:

1
2
3
4
5
6
App3[1594:10b] Creating the instance of NSObject
App3[1594:10b] try block
App3[1594:10b] *** -[NSObject doNothing]: unrecognized selector sent to instance 0x105950
App3[1594:10b] catch block
App3[1594:10b] main: Caught NSInvalidArgumentException: *** -[NSObject doNothing]: unrecognized selector sent to instance 0x105950
App3[1594:10b] finally block

Podemos tratar diversas exception em um único bloco @try, utilizando vários blocos @catch um em seguida do outro. Lembrando que você deve tratar primeiro as exceptions mais específicas e depois as mais genéricas. Veja um exemplo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
@try {
  //codigo aqui
}
@catch( MyCustomException *exception ) {
  //tratamento da exception aqui  
}
@catch( NSException *exception ) {
  //tratamento da exception aqui  
}
@finally {
  //codigo sempre executado aqui  
}

Agora vou demonstrar o uso da diretiva @throw que serve para lançar uma nova exception, seu uso é bem simples bastando apenas informar a instancia da exception que será lançada.

1
2
3
4
5
6
7
8
@try {
  NSLog( @"try block" );
  NSException *exception = [NSException exceptionWithName:@"HotTeaException" reason:@"The tea is too hot"  userInfo:nil];
  @throw exception;
}
@catch( NSException *exception ) {
  NSLog(@"main: Caught %@: %@", [exception name], [exception  reason]);
}

No exemplo anterior repare que não utilizei a diretiva @finally apenas para demonstrar que seu uso não é obrigatorio. O resultado apresentado desse código é:

1
2
App3[1886:10b] try block
App3[1886:10b] main: Caught HotTeaException: The tea is too hot

Com isso já temos um bom conhecimento de como tratar exceptions em nosso código Objective-C.

Comments »


Agora também no twitter @rodrigolazoti

Ok, ok! Eu sei que é um pouco tarde, mas somente agora resolvi me cadastrar no twitter.

Aproveitei e fiz um cadastro meu e outro para o site do MacDevelopers.

Então para quer quiser me acompanhar o meu endereço é http://twitter.com/rodrigolazoti e o do MacDevelopers é http://twitter.com/macdevelopers

Vamos “twittar” ! :D

Comments »


Trabalhando com Strings em Objective-C

Diferente do C puro que para utilizarmos uma cadeia de caracteres temos que criar um array ( char[] ), em Object-C temos 2 classes que são utilizadas para representar Strings em código Objective-C, elas são:

NSString e NSMutableString( subclasse de NSString ).

Uma string imutável (NSString) é definida não sua criação e não pode mais ser alterada, enquanto uma string mutável (NSMutableString) pode ter seu conteúdo alterado após sua criação. Com base nessas informações, entendemos que devemos utilizar NSString quando uma string não precisar ser alterada depois de sua criação e caso contrário devemos utilizar a classe NSMutableString.

Podemos criar uma String de 2 formas, utilizando métodos das classes NSString e NSMutableString ou o construtor @.

1
2
NSString *texto1 = @"Minha String";
NSString *texto2 = [NSString stringWithUTF8String :"Nova String"];

Para comparar strings, você pode utilizar o operador == ou o metodo isEqualToString, utilizando o operador == a comparação é feita utilizando os ponteiros das variáveis e utilizando o método isEqualToString a comparação é feita utilizando o conteúdo das duas strings.

1
2
3
4
5
6
NSString *texto1 = @"Minha String";
NSMutableString *texto2 = [[NSMutableString alloc] initWithString:@"Minha "];
[texto2 appendString: @"String"];

[texto1 isEqualToString: texto2]; // retorna false
NSBool *resultado = (texto1 == texto2); //retorna true

A classe NSString fornece diversos métodos para ajudar o desenvolvedor, para conhece-los o ideal é ler a documentação da classe disponível na Apple Developer Connection.

Vou incluir alguns exemplos abaixo para demostrar alguns recursos que a classe NSString fornece:

1
2
3
NSString *texto1 = @"Mac";
NSString *texto2 = [texto1 stringByAppendingString:@" Developers"];
// texto2 tera o valor @"Mac Developers"

No exemplo acima criei uma instância de NSString chamada texto1 e depois criei outra instância chamada texto2 utilizando o valor da variavel texto1 e adicionando outro valor no final.

1
2
3
NSString *numeros = @"0123456789";
NSString *parte = [numeros substringToIndex:4];
// parte é igual a @"0123"

No exemplo acima criei uma instância de NSString chamada numeros com o valor “0123456789” e depois criei uma segunda instância de NSString chamada parte onde seu valor sera os 4 primeiros caracteres da variavel numeros.

Com isso já sabemos o básico de como utilizar as classes NSString e NSMutableString em Objective-C.

Comments »


iPhone SDK e iPhone OS 3.1 Beta 2 Liberados para Desenvolvedores

A Apple acabou de disponibilizar o Beta 2 do SDK e Sistema Operacional do iPhone. Algumas novidades contidas nesse novo pre-release do SDK são:

_**Instruments can now profile your application on a device via WiFi connection. Read the release notes for instructions on how to set this up for your devices. ** _

_**Organizer: the iPhone Development grouping now collects crash logs, install bundles, and provisioning profiles in a single location ** _

iPhone OS 3.1 Simulator uses frameworks more closely matching the device.

Saiba mais em http://developer.apple.com/iphone/

Comments »


Criptografia Triple DES em Java

Um dos posts que mais foram acessados e comentados em meu blog foi um escrito sobre Criptografia em Java utilizando Hashs criptográficos.

Depois de receber alguns pedidos resolvi escrever este novo post utilizando no exemplo uma criptografia do tipo Triple DES, com esta criptografia podemos encriptografar e descriptografar informações utilizando Java.

Triple DES é a mais segura versão do algoritmo original Data Encryption Standard (DES) e você pode saber sobre este algoritmo aqui.

Agora vamos a implementação do algoritmo, eu criei uma classe simples que fornece dois métodos de instância para encriptografar e descriptografar uma String.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package br.com.rodrigolazoti;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * Class that supplies a criptography of triple type DES.
 * @author Rodrigo Lazoti
 * @since 05/07/2009
 */
public class CryptographyTripleDES {
   private Cipher cipher;
   private byte[] encryptKey;
   private KeySpec keySpec;
   private SecretKeyFactory secretKeyFactory;
   private SecretKey secretKey;

   /**
   * Method that create a new instance of class.
   * @return
   * @throws InvalidKeyException
   * @throws UnsupportedEncodingException
   * @throws NoSuchAlgorithmException
   * @throws NoSuchPaddingException
   * @throws InvalidKeySpecException
   */
   public static CryptographyTripleDES newInstance() throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException {
     return new CryptographyTripleDES();
   }

   /**
   * Default Constructor.
   * @throws UnsupportedEncodingException
   * @throws NoSuchAlgorithmException
   * @throws NoSuchPaddingException
   * @throws InvalidKeyException
   * @throws InvalidKeySpecException
   */
   private CryptographyTripleDES() throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException {
     String key = "http://www.rodrigolazoti.com.br";
     encryptKey = key.getBytes( "UTF-8" );
     cipher = Cipher.getInstance( "DESede" );
     keySpec = new DESedeKeySpec( encryptKey );
     secretKeyFactory = SecretKeyFactory.getInstance( "DESede" );
     secretKey = secretKeyFactory.generateSecret( keySpec );
   }

   /**
   * Method that encrypts a value.
   * @param value
   * @return
   * @throws InvalidKeyException
   * @throws IllegalBlockSizeException
   * @throws BadPaddingException
   * @throws UnsupportedEncodingException
   */
   public String encrypt( String value ) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
     cipher.init( Cipher.ENCRYPT_MODE, secretKey );
     byte[] cipherText = cipher.doFinal( value.getBytes( "UTF-8" ) );
     BASE64Encoder encoder = new BASE64Encoder();
     return encoder.encode( cipherText );
   }

   /**
   * Methot that decrypts a value.
   * @param value
   * @return
   * @throws InvalidKeyException
   * @throws IllegalBlockSizeException
   * @throws BadPaddingException
   * @throws IOException
   */
   public String decrypt( String value ) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {
     cipher.init( Cipher.DECRYPT_MODE, secretKey );
     BASE64Decoder dec = new BASE64Decoder();
     byte[] decipherText = cipher.doFinal( dec.decodeBuffer( value ) );
     return new String( decipherText );
   }

}

A seguir criei uma pequena classe para realizar um teste:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package br.com.rodrigolazoti;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class TestCryptographyTripleDES {

  public static void main( String[] args ) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, IOException {

   CryptographyTripleDES cryptography = CryptographyTripleDES.newInstance();
   String value = "Rodrigo Lazoti";
   System.out.println( "Valor utilizado => " + value );
   String encryptedValue = cryptography.encrypt( value );
   System.out.println( "Valor criptografado => " + encryptedValue );
   String decryptedValue = cryptography.decrypt( encryptedValue );
   System.out.println( "Valor descriptografado => " + decryptedValue );
 }

}

O resultado do teste é:

1
2
3
Valor utilizado => Rodrigo Lazoti
Valor criptografado => RgYlMeQBUcyx6419bKlqRw==
Valor descriptografado => Rodrigo Lazoti

Com isso já temos uma boa base de como utilizar este tipo de criptografia em aplicações Java.

Comments »