Domanda

Sto cercando di creare un metodo che controlli una stringa nulla/nil/vuota e sto cercando di farlo funzionare come categoria ma senza fortuna.

Sto usando questo codice, in base alle risposte in questo argomento:

@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

Eppure quando provo a usarlo questo è ciò che ottengo:

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

Questo mi sconcerta e posso solo supporre che una qualche combinazione di iOS5/ARC stia costringendo l'oggetto nil a una stringa/puntatore vuoto.Il debugger mostra la stringa come 0x0, ma quando utilizzo my isNullOrEmpty metodo, ottengo falso.

È stato utile?

Soluzione

return self == nil

Questo non potrà mai accadere.Se provi a inviare isNullOrEmpty (o qualsiasi altro messaggio) a nil, non accade nulla (objc_msgSend(), la funzione preposta all'invio dei messaggi, verifica a nil ricevitore come una delle prime cose che fa e interrompe).

self == (id)[NSNull null]

Anche questo non accadrà mai.Se invii isNullOrEmpty a un oggetto di cui è un'istanza NSNull, il tuo metodo qui, che è un metodo attivo NSString, non verrà chiamato.Invece, NSNullsarà la versione di (che probabilmente non esiste).

Allo stesso modo, ([self respondsToSelector:@selector(count)] && [(NSArray *) self count]) non accadrà mai.Se l'oggetto È UN NSArray, Poi isNullOrEmpty non verrà mai eseguito, perché, ancora una volta, è un metodo di NSString.

Di conseguenza, [(NSData *) self length] non fa quello che pensi che faccia. NSString istanze Fare rispondere a length, ma lanciando l'oggetto a NSData non utilizza il NSData versione del metodo: finisce comunque come NSString versione di length, perché l'oggetto in realtà lo è UN NSString (il casting avviene solo in fase di compilazione;non può cambiare nulla in fase di esecuzione).

[self isEqualToString:@"(null)"]

Qui sembra che tu stia controllando nil ancora una volta, ma vieni ingannato dal rappresentazione Quello NSLog sceglie quando stampare nil:

NSLog(@"%@", nil);

Questo viene visualizzato (null) nella console, ma ciò non significa che l'oggetto stesso sia una stringa con quei caratteri. NSLog sceglie semplicemente la stringa da visualizzare nil.*

Molte delle cose che stai facendo richiederebbero che questo fosse in una categoria NSObject, in modo che il metodo volevo infatti essere chiamato anche se l'oggetto non era an NSString.

Per verificare la presenza di una stringa composta solo da spazi bianchi, tutto ciò che serve è il confronto con la stringa vuota @"" dopo aver tagliato gli spazi bianchi:

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

*E ancora meglio, farlo NSLog(@"%@", [NSNull null]); visualizza <null> (parentesi angolari invece di parentesi), meravigliosamente confuse le prime volte che incontri NSNull.

Altri suggerimenti

Un altro approccio può essere quello di definire una semplice macro.

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

È semplice ed efficace.Se non ti piacciono i macro, puoi sempre convertirlo in una chiamata funzione senza influire sul resto del codice.

- Aggiornamento:

@bryan ha sollevato un buon punto.Una funzione in linea è un ottimo modo per andare.Ecco una macro aggiornata che valuterà ST solo una volta.

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

In OBIETTIVE-C, l'invio di un messaggio a nil restituirà sempre 0 (o NO, uno struct zero-out, null, ecc., A seconda del tipo di ritorno dichiarato).Il metodo isNullOrEmpty che hai scritto non verrà effettivamente invocato quando si invia isNullOrEmpty a nil.Vedere la risposta accettata a inviando un messaggio a nil? per ulteriori informazioni. Forse potresti cambiare il tuo metodo per essere isNotNullOrEmpty.Quindi un valore di ritorno di 0 quando si invia isNotNullOrEmpty a nil ha senso.

Non stai chiamando il tuo metodo, ma Invio di un messaggio a Nil .

Questo è il comportamento previsto.Stai inviando un messaggio a nil dopo tutto.Quindi sta restituendo né nil (o qualche altro valore 0).Quali cortocircuiti per false, in modo che '0' sia stampato nei casi indicati di seguito:

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

È anche possibile confermare il messaggio non viene chiamato per quei casi impostando un punto di interruzione nel tuo nuovo metodo di categoria.

Come altri hanno detto, chiamare [nil isNullOrEmpty]; non eseguirà effettivamente il tuo metodo.L'oggetto nil è solo quello: vuoto stesso.

Come soluzione, vorrei dire che non è perché sei in una lingua orientata agli oggetti che non devi mai usare le funzioni.

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;   
}
.

In realtà ho appena riparato questo problema ruotandolo come così

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

Quindi invece di isnoulrorwhithace è il suo isnotnullrorwhitespace.

Ecco il mio metodo di controllo null / vuoto

- (NSString *) NULLINPUTINITWithString: (NSString *) Inspstring {

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 ;
.

}

Hai pensato di creare un metodo di classe su una categoria che estende NSString?

nsstring + nstringextensions.h

#import <Foundation/Foundation.h>

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

nsstring + nstringextensions.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
.

Allora lo usi come questo:

#import "NSString+NSStringExtensions.h"
...
NSLog([NSString isNilOrEmpty:@""] ? @"1":@"0");
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top