Aprenda Objective-C

  • Página Inicial
  • Contato!
  • Tudo sobre Objective-C Parte 1!
  • Tudo sobre Objective-C Parte 2!
  • Tudo sobre Objective-C Parte 3!
  • Tudo sobre Objective-C Parte 4!
  • Tudo sobre Objective-C Parte 3

    Métodos

    Basicamente, um procedimento é um método que não retorna nada, como este:

    
    void saudacao();
    
    int main(int argc, const char *argv[]) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        saudacao();
    
        [pool drain];
    
        return 0;
    }
    
    void saudacao() {
        NSLog(@"Olá, usuário! Bom dia!");
    }
    
    

    Com um parâmetro:

    
    void saudacao(const char *nome);
    
    int main(int argc, const char *argv[]) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        saudacao("Fulano");
    
        [pool drain];
    
        return 0;
    }
    
    void saudacao(const char *nome) {
        NSLog(@"Olá, %s! Bom dia!", nome);
    }
    
    

    Com isso podemos criar métodos para códigos grandes, por exemplo:

    
    void datas();
    
    int main(int argc, const char *argv[]) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        datas();
    
        [pool drain];
    
        return 0;
    }
    
    void datas() {
        NSDate *atual = [NSDate date];
        NSDateFormatter *formataData = [[NSDateFormatter alloc] init];
        NSDateFormatter *formataHora = [[NSDateFormatter alloc] init];
        NSDateFormatter *formataSem = [[NSDateFormatter alloc] init];
    
        [formataData setDateFormat: @"dd/MM/yyyy"];
        [formataHora setDateFormat: @"HH:mm:ss"];
        [formataSem setDateFormat: @"EEEE"];
    
        NSString *data = [formataData stringFromDate: atual];
        NSString *hora = [formataHora stringFromDate: atual];
        NSString *sem = [formataSem stringFromDate: atual];
    
        NSLog(@"Hoje é dia %@, %@, e a hora é %@.", data, sem, hora);
    }
    
    

    Exemplo de função, com parâmetro e retorno (o tipo é o tipo de retorno do método):

    
    int multi(int n1, int n2);
    
    int main(int argc, const char *argv[]) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        NSLog(@"%d", multi(10, 5));
    
        [pool drain];
    
        return 0;
    }
    
    int multi(int n1, int n2) {
        return n1 * n2;
    }
    
    

    PS: Objective-C não suporta sobrecarga de métodos.

    Podemos dividir os métodos em arquivos separados, onde a declaração dos métodos vão num arquivo .h e a implementação num arquivo .m, depois é só incluir o arquivo .h com um include no código principal (com aspas). Dessa forma:

    Arquivo funcoes.h:

    
    #ifndef FUNCOES_H_INCLUDED
    #define FUNCOES_H_INCLUDED
    
    int multi(int n1, int n2);
    
    #endif // FUNCOES_H_INCLUDED
    
    

    Arquivo funcoes.m:

    
    #include "funcoes.h"
    
    int multi(int n1, int n2) {
        return n1 * n2;
    }
    
    

    Makefile:

    
    programa: main.o funcoes.o
        gcc main.o funcoes.o -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -l objc -lgnustep-base -fconstant-string-class=NSConstantString -lm -ldl -fobjc-exceptions -o programa -no-pie
    
    main.o: main.m funcoes.o
        gcc -c main.m -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -l objc -lgnustep-base -fconstant-string-class=NSConstantString -lm -ldl -fobjc-exceptions -o main.o
    
    funcoes.o: funcoes.m funcoes.h
        gcc -c funcoes.m -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ -l objc -lgnustep-base -fconstant-string-class=NSConstantString -lm -ldl -fobjc-exceptions -o funcoes.o
    
    

    Tratamento de Erros

    Vamos considerar esse código para calcular uma divisão:

    
    int n1, n2, res;
    
    printf("Digite o numerador: ");
    scanf("%d", &n1);
    printf("Digite o denominador: ");
    scanf("%d", &n2);
    
    res = n1 / n2;
    
    NSLog(@"A divisão entre %d e %d é igual a %d.", n1, n2, res);
    
    

    Se tentarmos dividir qualquer número por zero, ele dará erro e lançara uma exceção.

    Para tratarmos esse erro, usamos o bloco try catch para isso:

    
    @try {
    
    }
    @catch(NSException *ex) {
    
    }
    @finally { // Opcional
    
    }
    
    

    No caso, colocamos o código suscetível a erro dentro do try, ele executará ele todo ou parará quando encontrar um erro, e passará a executar o que está dentro do catch. O finally executará com erro ou não.

    O código acima ficaria assim:

    
    @try {
        int n1, n2, res;
    
        printf("Digite o numerador: ");
        scanf("%d", &n1);
        printf("Digite o denominador: ");
        scanf("%d", &n2);
    
        res = n1 / n2;
    
        NSLog(@"A divisão entre %d e %d é igual a %d.", n1, n2, res);
    }
    @catch(NSException *ex) {
        NSLog(@"O código deu erro: %@.", ex.name);
    }
    @finally {
        NSLog(@"Conclusão do código!");
    }
    
    

    PS: Podemos ter vários catch num mesmo bloco try, cada um com uma exceção específica.

    No entanto, o código acima não pega a exceção como queremos, nós podemos usar um @throw para isso, que nem precisa estar dentro do try, mas numa função, como abaixo:

    
    int divisao(int n1, int n2);
    
    int main(int argc, const char *argv[]) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        @try {
            int n1, n2, res;
    
            printf("Digite o numerador: ");
            scanf("%d", &n1);
            printf("Digite o denominador: ");
            scanf("%d", &n2);
    
            res = divisao(n1, n2);
    
            NSLog(@"A divisão entre %d e %d é igual a %d.", n1, n2, res);
        }
        @catch(NSException *ex) {
            NSLog(@"O código deu erro: %@.", ex.name);
        }
        @finally {
            NSLog(@"Conclusão do código!");
        }
    
        [pool drain];
    
        return 0;
    }
    
    int divisao(int n1, int n2) {
        if(n2 == 0) {
            [NSException raise: @"É impossível dividir por zero" format: @""];
        }
    
        return n1 / n2;
    }
    
    

    Introdução aos Ponteiros

    Os ponteiros são variáveis especiais que contém um endereço de memória armazenado, em vez de dados comuns, esse endereço é, no geral, a posição na memória de uma outra variável. Dessa forma, a variável que contém esse endereço aponta para a outra variável, daí o nome ponteiro.

    O & pega o endereço de memória, ou envia conteúdos para ele. O * pega o conteúdo que está no endereço apontado, ou envia para o mesmo.

    Veja um exemplo simples de ponteiro:

    
    int num = 50;
    int *pont;
    
    pont = #
    
    NSLog(@"Endereço de num: %p", &num);
    NSLog(@"Conteúdo de num: %d", num);
    NSLog(@"Endereço de pont: %p", &pont);
    NSLog(@"Endereço apontado por pont: %p", pont);
    NSLog(@"Conteúdo apontado por pont: %d", *pont);
    
    free(pont); // Liberando memória do ponteiro.
    
    

    PS: Os ponteiros podem ser de qualquer tipo, mas eles devem ser do mesmo tipo da variável que ele aponta (por exemplo, um ponteiro int só pode apontar uma variável int, um ponteiro double só pode apontar uma variável double e assim por diante).

    System e Getenv

    Usamos o System e o Getenv da mesma forma que em C, como podem ver:

    
    chdir("/home"); // Inclua unistd.h
    
    system("ls"); // Inclua stdlib.h
    
    

    Usando uma variável de ambiente do sistema:

    
    chdir(getenv("HOME"));
    
    system("ls");