I'm trying to create a method which checks for a null/nil/empty string, and I'm trying to get it working as a category but having no luck.
I'm using this code, based on answers in this topic:
#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
Yet when I try to use this this is what I get:
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
This is baffling me, and I can only assume that some combination of iOS5/ARC is causing the nil object to be coerced to a blank string/pointer. The debugger shows the string as 0x0, yet when I use my isNullOrEmpty method, I get false.
return self == nil
This can never happen. If you try to send isNullOrEmpty (or any other message) to nil, nothing happens (objc_msgSend(), the function responsible for message dispatch, checks for a nil reciever as one of the first things it does and aborts).
self == (id)[NSNull null]
This will also never happen. If you send isNullOrEmpty to an object that's an instance of NSNull, your method here, which is a method on NSString, will not be called. Instead, NSNull's version (which probably doesn't exist) will be.
Likewise, ([self respondsToSelector:#selector(count)] && [(NSArray *) self count]) is never going to happen. If the object is an NSArray, then isNullOrEmpty will never run, because, again, it's a method of NSString.
Correspondingly, [(NSData *) self length] doesn't do what you think it does. NSString instances do respond to length, but casting the object to NSData doesn't use the NSData version of the method -- it still ends up as the NSString version of length, because the object actually is an NSString (casting only happens at compile-time; it can't change anything at run-time).
[self isEqualToString:#"(null)"]
Here you appear to be checking for nil again, but you are being misled by the representation that NSLog chooses when it prints nil:
NSLog(#"%#", nil);
This displays (null) in the console, but that doesn't mean that the object itself is a string with those characters. NSLog just chooses that string to display for nil.*
Several of the things you are doing would require this to be in a category on NSObject, so that the method would in fact be called even if the object was not an NSString.
To check for a string consisting only of whitespace, all you need is the comparison to the empty string #"" after trimming whitespace:
NSString * trimmedSelf = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// Then either:
[trimmedSelf isEqualToString:#""];
// Or:
([trimmedSelf length] == 0);
*And even better, doing NSLog(#"%#", [NSNull null]); displays <null> (angle brackets instead of parentheses), wonderfully confusing the first few times you encounter NSNull.
Another approach can be to define a simple macro.
#define NSStringIsNullOrEmpty(str) ((str==nil) || [(str) isEqualToString:#""])
It's simple and effective. If you do not like macros you can always convert it to a function call without affecting the rest of your code.
-- Update:
#Bryan has raised a good point. An inline function is a great way to go. Here is an updated macro that will evaluate str only once.
#define NSStringIsNullOrEmpty(str) ({ NSString *_str=(str); ((tmp==nil) || [tmp isEqualToString:#""]);})
In Objective-C, sending a message to nil will always return 0 (or NO, a zeroed-out struct, NULL, etc., depending on the declared return type). The isNullOrEmpty method that you wrote won't actually be invoked when you send isNullOrEmpty to nil. See the accepted answer to Sending a message to nil? for more information.
Perhaps you could change your method to be isNotNullOrEmpty. Then a return value of 0 when sending isNotNullOrEmpty to nil will make sense.
You aren't calling your method, but sending a message to nil.
This is expected behavior. You are sending a message to nil after all. So it is returning either nil (or some other 0 value). Which short circuits to false so that '0' is printed in the cases shown below:
NSLog([s1 isNullOrEmpty] ? #"1":#"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? #"1":#"0"); // prints 0
You can even confirm your message is not being called for those cases by setting a breakpoint in your new category method.
Like others have said, calling [nil isNullOrEmpty]; will not actually run your method. The nil object is just that : empty itself.
As a solution, I'd like to say that it's not because you're in an Object-Oriented language that you must never use functions.
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;
}
actually I just fixed this problem by turning it around like so
-(BOOL) isNotNullOrWhiteSpace
{
return [self length] != 0 && [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] != 0;
}
so instead of isNullOrWhiteSpace it's isNotNullOrWhiteSpace.
Here's my method of checking null/empty
-(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 ;
}
Have you thought about creating a class method on a category that extends 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
Then you use it like this:
#import "NSString+NSStringExtensions.h"
...
NSLog([NSString isNilOrEmpty:#""] ? #"1":#"0");
I need to remove all emoijs from a NSString.
So far i am using this NSString extension ...
- (NSString*)noEmoticon {
static NSMutableCharacterSet *emoij = NULL;
if (emoij == NULL) {
emoij = [[NSMutableCharacterSet alloc] init];
// unicode range of old emoijs
[emoij removeCharactersInRange:NSMakeRange(0xE000, 0xE537 - 0xE000)];
}
NSRange range = [self rangeOfCharacterFromSet:emoij];
if (range.length == 0) {
return self;
}
NSMutableString *cleanedString = [self mutableCopy];
while (range.length > 0) {
[cleanedString deleteCharactersInRange:range];
range = [cleanedString rangeOfCharacterFromSet:emoij];
}
return cleanedString;
}
... but that does not work at all. The range.length is always 0.
So the general question is : How can i remove a range of unicode characters from a NSString?
Thanks a lot.
It seems to me that in the above code the emoij variable is eventually an empty set. Didn't you mean to addCharactersInRange: rather than to removeCharactersInRange:?
I want to ask a question about the objective C. Does the NSString * contains some functions to check the NSString * contains some string in the UITextField.text? For example
NSString *checkString = #"abcd%"
if(checkString contains '%') // I want this function
return YES;
else
return NO;
if([checkString rangeOfString:#"%"].location != NSNotFound)
// hooray!
You can use - (NSRange)rangeOfString:(NSString *)aString. The code will look something like:
NSRange range = [UITextField.text rangeOfString:#"!"];
if (range.length > 0){
NSLog(#"String contains '!'");
}
else {
NSLog(#"No '!' found in string");
}
The code from the previous post is not correct
NSRange range = [UITextField.text rangeOfString:#"!"];
if (range.length >= 0){
NSLog(#"String contains '!'");
}
else {
NSLog(#"No '!' found in string");
}
It should be "range.length > 0"
This question already has answers here:
How do I check if a string contains another string in Objective-C?
(21 answers)
Closed 8 years ago.
How can I tell if a string contains something? Something like:
if([someTextField.text containsString:#"hello"]) {
}
You could use:
if ( result && [result rangeOfString:#"hello"].location != NSNotFound ) {
// Substring found...
}
You have to use - (NSRange)rangeOfString:(NSString *)aString
NSRange range = [myStr rangeOfString:#"hello"];
if (range.location != NSNotFound) {
NSLog (#"Substring found at: %d", range.location);
}
View more here: NSString rangeOfString
If the intent of your code is to check if a string contains another string you can create a category to make this intent clear.
#interface NSString (additions)
- (BOOL)containsString:(NSString *)subString;
#end
#implementation NSString (additions)
- (BOOL)containsString:(NSString *)subString {
BOOL containsString = NO;
NSRange range = [self rangeOfString:subString];
if (range.location != NSNotFound) {
containsString = YES;
}
return containsString;
}
#end
I have not compiled this code, so maybe you should have to change it a bit.
Quentin
What is the value of a UITextField when it is empty? I can't seem to get this right.
I've tried (where `phraseBox' it the name of the said UITextField
if(phraseBox.text != #""){
and
if(phraseBox.text != nil){
What am I missing?
// Check to see if it's blank
if([phraseBox.text isEqualToString:#""]) {
// There's no text in the box.
}
// Check to see if it's NOT blank
if(![phraseBox.text isEqualToString:#""]) {
// There's text in the box.
}
found this at apple discussions when searching for the same thing,thought ill post it here too.
check the length of the string :
NSString *value = textField.text;
if([value length] == 0) {
}
or optionally trim whitespaces from it before validation,so user cannot enter spaces instead.works well for usernames.
NSString *value = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if([value length] == 0) {
// Alert the user they forgot something
}
Try following code
textField.text is a string value so we are checking it like this
if([txtPhraseBox.text isEqualToString:#""])
{
// There's no text in the box.
}
else
{
NSLog(#"Text Field Text == : %# ",txtPhraseBox.text);
}
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString *fullText = [textField.text stringByAppendingString:string];
if ((range.location == 0) && [self isABackSpace:string]) {
//the textFiled will be empty
}
return YES;
}
-(BOOL)isABackSpace:(NSString*)string {
NSString* check =#"Check";
check = [check stringByAppendingString:string];
if ([check isEqualToString:#"Check"]) {
return YES;
}
return NO;
}
Use for text field validation:
-(BOOL)validation{
if ([emailtextfield.text length] <= 0) {
[UIAlertView showAlertViewWithTitle:AlertTitle message:AlertWhenemailblank];
return NO; }
return YES;}
Actually, I ran into slight problems using Raphael's approach with multiple text fields. Here's what I came up with:
if ((usernameTextField.text.length > 0) && (passwordTextField.text.length > 0)) {
loginButton.enabled = YES;
} else {
loginButton.enabled = NO;
}
Validation against empty UITextfield. if you don't want that UITextField should not accept blank white spaces. Use this code snippet:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *resultingString = [textField.text stringByReplacingCharactersInRange: range withString: string];
NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
if ([resultingString rangeOfCharacterFromSet:whitespaceSet].location == NSNotFound) {
return YES;
} else {
return NO;
}
}