09 Set, 2011 12:00
2 dicas simples para trabalhar com NSNull
Apesar de substituir o nil, NSNull possui uma diferença fundamental: a chamada de métodos de NSNull causa erros, enquanto a nil sempre retorna nil.
id meuNil = nil;
[meuNil meuMetodoQualquer]; //retorna nil!
id meuNull = [NSNull null];
[meuNil meuMetodoQualquer] //'NSInvalidArgumentException', reason: '-[NSNull meuMetodoQualquer]: unrecognized selector sent to instance
Esse comportamento obriga-nos a sempre tratar a possibilidade de um dado objeto ser NSNull.
//meuObjeto pode ser NSNull em alguns cenários
if ((NSNull *)meuObjeto != [NSNull null]) {
//meuObjeto é válido, então eu faço uma determinada ação
}
else {
//meuObjeto é NSNull então eu faço o tratamento
}
Para facilitar a nossa vida, criamos duas técnicas que passaremos para vocês agora.
Dica 1: Convertendo NSNull em nil automaticamente
É comum o caso em que você simplesmente queira que, onde houver um NSNull, este se comporte como um nil - por exemplo, para atribuir a uma segunda variável. O código padrão para tratar esse comportamento poderia ser:
if ((NSNull *)meuObjeto != [NSNull null]) {
outroObjeto.propriedadeQualquer = meuObjeto;
}
else {
outroObjeto.propriedadeQualquer = nil;
}
Numa situação onde você esteja realizando muitas atribuições como a acima (como, por exemplo, copiando diversos valores de um NSDictionary para o seu objeto), seu código poderia ficar bem extenso. Para evitar isso, poderíamos fazer algo como
outroObjeto.propriedadeQualquer = [meuObjeto orNil];
Simples, não? Se meuObjeto for qualquer objeto válido, orNil retornará o próprio objeto. Caso contrário, retornará nil.
Mas como fazer esse truque funcionar? Resposta: Categories! Em suma, no Objective C é possível adicionar métodos a uma classe pré-existente sem precisar criar uma subclasse. O código para isso é muito trivial.
NSObject+NSNullExtras.h
@interface NSObject (NSNullExtras)
- (id)orNil;
@end
NSObject+NSNullExtras.m
#import "NSObject+NSNullExtras.h"
@implementation NSObject (NSNullExtras)
- (id)orNil {
return self;
}
@end
@implementation NSNull (NSNullExtras)
- (id)orNil {
return nil;
}
@end
Repare que é necessário criar o método em NSObject para que qualquer objeto possa responder a essa chamada e sobrescrevê-lo em NSNull.
Para utilizar, basta importar NSObject+NSNullExtras.h onde for necessário.
Dica 2: Descrição padrão
Outro caso recorrente é o de chamar o método description para obter um NSString a partir do seu objeto. NSNull, contudo, vira "<null>", o que pode não ser interessante.
Para resolver essa situação, criamos o método descriptionWithDefault:. Ex.
self.label.text = [meuObjeto descriptionWithDefault:@"não informado"];
Se meuObjeto for válido, o label do exemplo receberá a sua descrição normal, caso contrário, receberá a string "não informado". A técnica para esse método é semelhante a do orNil. Você pode baixar o código de ambos aqui.