terça-feira, 9 de outubro de 2012

NSPredicate no iOS

Olá povo,

Na última Campus Party Recife, assisti uma palestra do professor Fernando Castor da UFPE, e uma coisa que ele falou me chamou a atenção (veja minuto 29:58): "Java é igual ao Marlon Brando, quando chegou era bonitão, mas hoje envelheceu"(e o ator já morreu).
Estou atualmente em um projeto com iOS, e recentemente fiz um curso de Adobe Air e outro de Windows Phone. O que pude notar, é que em todos esses ambientes, as linguagens evoluíram e estão trazendo dinamismos que facilitam bastante a vida do desenvolvedor. O conceito de Binding utilizado pelo Air e pelo WP7 é um exemplo desse tipo de coisa.
Depois dessa introdução poética :) hoje quero falar de um conceito bem bacana do Objective-C, linguagem utilizada para criar aplicativos para o iOS: os predicates. Eles permitem fazer buscas em listas de objetos sem ter que iterar sobre eles. Felipe Vasconcelos me mostrou isso e achei bem bacana! :)

#define KEY_NOME  @"nome"
#define KEY_IDADE @"idade"
#define KEY_PAI   @"pai"

@interface MinhaPessoa : NSObject
@property (strong, nonatomic) NSString *nome;
@property (assign, nonatomic) int idade;
@property (strong, nonatomic) MinhaPessoa *pai;
@end

@implementation MinhaPessoa

@end

int main(int argc, char *argv[])
{
  NSMutableArray *complexList = 
    [NSMutableArray new];

  // Adicionando um NSDictionary
  [complexList addObject: @{
    KEY_NOME  : @"Antônio",
    KEY_IDADE : @10,
    KEY_PAI   : @{ KEY_NOME : @"Fulano" }
  }];

  // Outro NSDictionary
  [complexList addObject: @{
    KEY_NOME  : @"Francisco",
    KEY_IDADE : @20,
    KEY_PAI   : @{ KEY_NOME : @"Fulano"}
  }];

  // Agora um objeto Pessoa
  MinhaPessoa *p  = [MinhaPessoa new];
  p.nome     = @"João";
  p.idade    = 30;
  p.pai      = [MinhaPessoa new];
  p.pai.nome = @"Cicrano";
  [complexList addObject:p];

  // De novo um NSDicionary
  [complexList addObject: @{
    KEY_NOME  : @"Nelson",
    KEY_IDADE : @28,
    KEY_PAI   : @{ KEY_NOME : @"Beltrano"}
  }];
  // E pra finalizar, outra Pessoa
  p          = [MinhaPessoa new];
  p.nome     = @"Glauber";
  p.idade    = 28;
  p.pai      = [MinhaPessoa new];
  p.pai.nome = @"Beltrano";
  [complexList addObject:p];

  // pai.nome (nome do pai que contenha B)
  NSString *attribute = [NSString 
    stringWithFormat:@"%@.%@", KEY_PAI, KEY_NOME];
  // predicado para a busca
  NSPredicate* predicate = [NSPredicate 
    predicateWithFormat:
      @"%K contains[cd] %@", attribute, @"B"];
  NSArray *resultado = [complexList 
    filteredArrayUsingPredicate:predicate];

  for (id item in resultado) {
    NSLog(@"%@", [item description]);
  }
}
O código acima mostra bem o dinamismo no Objective-C. Primeiro, criamos um array misturando dois tipos de objetos: NSDictionary e MinhaPessoa. Essas classes têm em comum que os atributos da classe MinhaPessoa são iguais às chaves usadas no dicionário.
Uma vez alimentado o array complexList, criamos um objeto NSPredicate que fará o filtro "pai.nome contains[cd] 'B'", ou seja, todos os objetos onde o nome do pai contenha "B". O 'cd' significa que a busca será case insensitive e que serão ignorados os acentos. Através do método filteredArrayUsingPredicate obtemos um array resultado com os objetos filtrados. Por fim, fazemos um foreach para percorrer os resultados.

Saiba mais sobre predicados aqui.

Qualquer dúvida, deixem seus comentários.

4br4ç05,
nglauber

Nenhum comentário: