Pergunta

Eu estou tentando criar um método que verifica a existência de um nulo/nulo/string vazia, e eu estou tentando fazê-lo funcionar como uma categoria, mas tendo nenhuma sorte.

Eu estou usando este código, baseadas no respostas este tópico:

@implementation NSString (NSStringExtension)
- (BOOL)isNullOrEmpty {
    return self == nil || 
    self == (id)[NSNull null] ||
    [@"" isEqualToString:self] || 
    [[self stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
    [self isEqualToString:@"(null)"]
     || ([self respondsToSelector:@selector(length)] && [(NSData *) self length] == 0)
     || ([self respondsToSelector:@selector(count)] && [(NSArray *) self count] == 0)
     || [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
}
@end

No entanto, quando tento utilizar este é isso que eu recebo:

NSLog([@"" isNullOrEmpty] ? @"1":@"0"); // prints 1
NSString *s1 = nil;
NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([args.itemName isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0

Isso é desconcertante de mim, e eu só posso supor que a combinação do iOS5/ARCO está causando o nil objeto a ser coagido a uma seqüência de caracteres em branco/ponteiro.O depurador mostra a seqüência de caracteres como 0 x 0, mas quando eu uso o meu isNullOrEmpty método, recebo falso.

Foi útil?

Solução

return self == nil

Isso nunca pode acontecer.Se você tentar enviar isNullOrEmpty (ou qualquer outra mensagem) para nil, não acontece nada (objc_msgSend(), a função responsável por envio de mensagem, verifica a existência de uma nil receptor como uma das primeiras coisas que ele faz e anula).

self == (id)[NSNull null]

Isso também irá acontecer nunca.Se você enviar isNullOrEmpty para um objeto que é uma instância de NSNull, seu método aqui, que é um método NSString, não será chamado.Em vez disso, NSNull's versão (que provavelmente não existe) vai ser.

Da mesma forma, ([self respondsToSelector:@selector(count)] && [(NSArray *) self count]) nunca vai acontecer.Se o objeto é um NSArray, e , em seguida, isNullOrEmpty nunca será executado, pois, mais uma vez, é um método de NSString.

Correspondentemente, [(NSData *) self length] não faz o que você acha que ele faz. NSString instâncias fazer responder length, mas o elenco do objeto para NSData não usar o NSData versão do método -- ele ainda termina como a NSString versão length, porque o objeto na verdade, é um NSString (fundição só acontece em tempo de compilação;ele não pode mudar nada em tempo de execução).

[self isEqualToString:@"(null)"]

Aqui você parecer ser de verificação para nil novamente, mas você está sendo enganado pelos representação que NSLog escolhe quando imprime nil:

NSLog(@"%@", nil);

Este apresenta (null) no console, mas isso não significa que o objeto em si é uma seqüência de caracteres com os personagens. NSLog é só escolher a que a seqüência de caracteres para exibir para nil.*

Várias das coisas que você está fazendo exigiria que este ser em uma categoria em NSObject, de modo que o método gostaria de no fato de ser chamada, mesmo se o objeto não era uma NSString.

Para verificar se uma string consistindo apenas de espaços em branco, tudo que você precisa é a comparação de seqüência de caracteres vazia @"" depois do corte de espaço em branco:

NSString * trimmedSelf = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// Then either:
[trimmedSelf isEqualToString:@""];
// Or:
([trimmedSelf length] == 0);

*E melhor ainda, fazendo NSLog(@"%@", [NSNull null]); apresenta <null> (colchetes em vez de parênteses), maravilhosamente confuso nas primeiras vezes que você encontrar NSNull.

Outras dicas

Outra abordagem pode definir uma macro simples.

#define NSStringIsNullOrEmpty(str) ((str==nil) || [(str) isEqualToString:@""])

É simples e eficaz.Se você não gosta de macros que você pode sempre convertê-lo para uma chamada de função, sem afetar o resto do seu código.

-- Update:

@Bryan levantou um bom ponto.Uma função in-line é uma ótima maneira de ir.Aqui está uma actualização macro que irá avaliar str apenas uma vez.

#define NSStringIsNullOrEmpty(str) ({ NSString *_str=(str); ((tmp==nil) || [tmp isEqualToString:@""]);})

Em objective-C, o envio de uma mensagem para nil sempre irá retornar 0 (ou NO, uma zerado-out, struct, NULL, etc., dependendo do tipo de retorno declarado).O isNullOrEmpty o método que você escreveu não, na verdade, ser invocada quando você enviar isNullOrEmpty para nil.Veja o aceite resposta O envio de uma mensagem para nil? para obter mais informações.

Talvez você pudesse mudar o seu método a ser isNotNullOrEmpty.Em seguida, um valor de retorno de 0 ao enviar isNotNullOrEmpty para nil vai fazer sentido.

Você não está chamando o seu método, mas o envio de uma mensagem para nil.

Este é o comportamento esperado.Você está enviando uma mensagem para nil depois de tudo.Então, ele está retornando ou nulo (ou algum outro valor 0).Que os curto-circuitos para false para que o " 0 " é impresso em casos mostrado abaixo:

NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0

Você pode até confirmar a sua mensagem não está sendo chamado para aqueles casos em que, por definição, um ponto de interrupção em sua nova categoria de método.

Como outros já disseram, chamando [nil isNullOrEmpty]; na verdade, não será executado o método.O nil objeto é apenas isso :esvaziar-se.

Como uma solução, eu gostaria de dizer que não é porque você está em uma linguagem Orientada a Objeto que você nunca deve usar funções.

BOOL IsStringNilOrEmpty(NSString*)str
{
    return str == nil ||
        str == null ||
        [@"" isEqualToString:str] ||
        [[str stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
        [str isEqualToString:@"(null)"]
        || ([str respondsToSelector:@selector(length)] && [(NSData *) str length] == 0)
        || ([str respondsToSelector:@selector(count)] && [(NSArray *) str count] == 0)
        || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;   
}

na verdade, eu só corrigiu este problema girando em torno de como isso

-(BOOL) isNotNullOrWhiteSpace
{
        return [self length] != 0 && [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] != 0;
}

assim, em vez de isNullOrWhiteSpace é isNotNullOrWhiteSpace.

Aqui está o meu método de verificação nulo/vazio

-(NSString*)NULLInputinitWithString:(NSString*)InputString {

if( (InputString == nil) ||(InputString ==(NSString*)[NSNull null])||([InputString isEqual:nil])||([InputString length] == 0)||([InputString isEqualToString:@""])||([InputString isEqualToString:@"(NULL)"])||([InputString isEqualToString:@"<NULL>"])||([InputString isEqualToString:@"<null>"]||([InputString isEqualToString:@"(null)"])||([InputString isEqualToString:@"NULL"]) ||([InputString isEqualToString:@"null"])))

    return @"";
else
    return InputString ;

}

Você já pensou em criar um método de classe em uma categoria que se estende NSString?

NSString+NSStringExtensions.h

#import <Foundation/Foundation.h>

@interface NSString(NSStringExtensions)
+(BOOL)isNilOrEmpty:(NSString*)string;
@end

NSString+NSStringExtensions.m

#import "NSString+NSStringExtensions.h"

@implementation NSString(NSStringExtensions)

+(BOOL)isNilOrEmpty:(NSString*)string
{
    if (nil == string)
    {
        return YES;
    }
    if (string.length == 0)
    {
        return YES;
    }
    return NO;
}

@end

Em seguida, você usá-lo assim:

#import "NSString+NSStringExtensions.h"
...
NSLog([NSString isNilOrEmpty:@""] ? @"1":@"0");
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top