I have a string
NSString hi;
and I don't know what values will get initialized to it. Could be nil, could be empty string, could be anything.
Are there any advantages to using
if (![hi length])
vs
if (![hi isEqualToString:#""])
It seems like both cases return the same values for empty string, nil, and any other type of string. I would guess length is better because it's more efficient. It just returns a variable, where as isEqualToString has to do a comparison.
They don't do the same thing.
[hi length] will return 0 for nil or an empty string and nonzero for any other string.
[hi isEqualToString:#""] will return 1 when hi is an empty string and 0 when hi is nil or any non-empty string.
In other words, the only value of hi for which the two lines of code give the same result is nil.
You probably wanted the behavior of option #1 (treating either nil or an empty string as "blank" and any other value as "not blank"), so that would be the one to use.
Are there any advantages to using if (![hi length])
Yes. It can check for an empty string and for a nil at the same time. You can't do this with isEqualToString:, since if the string is nil, then any message sent to it will return zero, so it won't appear to be equal to the empty string, hence requiring another check.
By the way, for clarity, you should consider using if (hi.length != 0).
I would do the following
if (hi && ![hi isEqualToString:#""]) {
}
![hi isEqualToString:#""] alone will get you a true if hi is nil.
Related
I am comparing two strings.
The problem is when my both strings are nil. I don't know when both strings comes nil then why control goes in success block.
I am using this code to compare strings:
if(![oldString isEqualToString:newString])
{
//in case both are nil control reaches here
needToShowPopup = YES;
break;
}
Edit: I want if only both strings are different then only my control will go inside if statement. My condition is failing when both are nil
If you want the if condition to only be evaluated when both strings are not nil then you can do:
if (oldString && newString && ![oldString isEqualToString:newString]) {
// both strings are set but they are not the same
}
The code you have will enter the if statement if oldString is nil regardless of the value of newString.
I think you are saying that you want the equivalent of [nil isEqualToString:nil] returning true. If that is the case your if can be written:
if(oldString ? ![oldString isEqualToString:newString] : newString)
Alternatively if you don't want the if to execute if either or both values are nil then your if can be written:
if(oldString && newString && ![oldString isEqualToString:newString])
HTH
Here's how I do it
if(oldString == newString || [oldString isEqualToString:newString]) {
// strings are the same
}
The first check oldString == newString compares the pointers. Either both pointers are the same memory address so they must by definition be equal, or both pointers are nil, so also equal
If that fails, then we call [oldString isEqualToString:newString], which compares the string contents. If either side is nil, then this will return false which is what we want, but if both sides are nil it will have caught it in the previous check and we won't get here :-)
If (oldstring!=null)
{
Your code...
}
In the following case where string is an NSString
if (string.length < 1)
{
return;
}
and string turns out to be nil the if statement will still evaluate correctly because in this case nil evaluates to 0.
However, is this recommended practice (by Clang or Apple) and are there any arguments against this and doing something closer to:
if (!string || string.length < 1)
{
return;
}
It's very common to do something like:
if (string.length) {
// string is not nil and the string has a non-zero length
} else {
// either string is nil or the length is zero
}
There is no need, in such a case, to check to see if string is nil or not.
When string is nil, you end up doing [nil length]. Calling any method on a nil pointer results in a value of "zero". How the "zero" is interpreted depends on the method's return type.
Primitive types appear as 0. BOOL appears as NO. Pointers appear as nil.
I'd say it's fine. Your alternate line is harder to understand at a glance and relies on the same logic (nil == 0) as the original line.
Some cases,for example working with strings that are made from response of requests, you should check the string, is a string, and not data!
NSString *string;
if ([string isKindOfClass:[NSString class]]) {
//
}
Cheers!
I have a class with an accessible method that passes back an NSString when called.
[MyClass getMyString]
The string variable in that class is actually assigned in the didSelectRowAtIndexPath: part of a table like this:
myString = cell.textLabel.text;
When I retrieve the string by calling that method, I assign it to another string in the class that called it and compare it to a string I have defined
NSString *mySecondString;
mySecondString = #"my value";
if(mySecondString == myString){
i = 9;
}
I have stepped through the code and every time it evaluates the if statement, it skips right past the i=9 and goes to the next else if statement. Why would this be? Why don't they evaluate to be the same value? If you hover your cursor over each of the values during debugging they will show they have the same value, but the code for some reason with not do as I expect it to do and assign 9 to i.
Any thoughts?
You're assuming that the C == operator does string equality. It doesn't. It does pointer equality (when called on pointers). If you want to do a real string equality test you need to use the -isEqual: method (or the specialization -isEqualToString: when you know both objects are strings):
if ([mySecondString isEqualToString:myString]) {
i = 9;
}
You are comparing pointers to strings, rather than the strings themselves. You need to change your code to
if (if([mySecondString isEqualToString:myString]) {
....
}
you can not use '==' to compare two NSString
you should to use [NSString isEqualToString:(NSString*)] to compare two string
You can not compare the two string using "==" this is for int and other values.
you can use below code for the comparing two string
if ([Firststring isEqualToString:Secondstring]) {
NSLog(#"Hello this both string is same ");
}
It's a basic concept of pointer, you are missing. (YES, myString and mySecondString are pointers to the string).
Now, if(mySecondString == myString) will go TRUE only if, both the pointers are pointing to the same location. (Which they won't in most cases)
You should be doing if ([mySecondString isEqualToString:myString]), which will be comparing your both string's content for equality.
I am trying to implement the code below without success. Basically, I want to set the display name to use thisPhoto.userFullName if it is not 'Blank", else show thisPhoto.userName instead.
UILabel *thisUserNameLabel = (UILabel *)[cell.contentView viewWithTag:kUserNameValueTag];
NSLog(#"user full name %#",thisPhoto.userFullName);
NSLog(#"user name %#",thisPhoto.userName);
if (thisPhoto.userFullName && ![thisPhoto.userFullName isEqual:[NSNull null]] )
{
thisUserNameLabel.text = [NSString stringWithFormat:#"%#",thisPhoto.userFullName];
}
else if (thisPhoto.userFullName == #"")
{
thisUserNameLabel.text = [NSString stringWithFormat:#"%#",thisPhoto.userName];
}
Currently, even if userFullName is blank, my userName is still not displayed on the screen.
I'd prefer
if([thisPhoto.userFullName length])
Use -length. This will be 0 whenever the string is nil or the empty string #"". You generally want to treat both cases identically.
NSString *fullName = [thisPhoto userFullName];
thisUserNameLabel.text = [fullName length]? fullName : [thisPhoto userName];
I see a few points here
First - if your userFullName instance variable is NSString* then doing simple comparison with nil is enough:
if (thisPhoto.userFullName)
Unless, of course, you explicitly set it to be [NSNull null], which then requires the condition you wrote.
Second - comparing strings is done with isEqualToString: method so second condition should be rewritten as:
if ([thisPhoto.userFullName isEqualToString:#""]) {
...
}
Third - there's logic flaw - If your userFullName IS equal to empty string (#"") the code would still fall to the first branch. I.e. empty string (#"") is not equal to [NSNull null] or simple nil. Hence you should write to branches - one to handle empty string and nil, other one for normal value. So with a bit of refactoring your code becomes like this:
thisUserNameLabel.text = [NSString stringWithFormat:#"%#",thisPhoto.userFullName];
if (!thisPhoto.userFullName || [thisPhoto.userFullName isEqualToString:#""]) {
// do the empty string dance in case of empty userFullName.
}
If, as I suppose, thisPhoto.userFullName is a NSString you may try
[thisPhoto.userFullName isEqualToString:#""]
The other two answers are correct, and beat me to it. Rather than just repeat what they have said - I'll point out something else.
[NSNull null] is used to store nil values in collection classes (NSArray, NSSet, NSDictionary) that don't allow nil values to be stored in them.
So unless you're checking values that you get from a collection - there is no point checking against [NSNull null]
// this assumes userFullName and userName are strings and that userName is not nil
thisUserNameLabel.text = [thisPhoto.userFullName length] > 0 ? thisPhoto.userFullName : thisPhoto.userName;
"Blank" means #"", but also #" " or #"\n". So I would trim userFullName and check the length of that string.
if ([[thisPhoto.userFullName stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
// it's blank!
}
I have setup an array full of words as objects. I am trying then trying to compare what the user enters in a uitextfield to an object in the array to see if they match.
I have captured a pointer to the uitextview in one of the delegate methods, however I cannot compare the text field contents to the object in the array. I assume that this is because one is a string and one is an array object ? Do I need to cast one of the variables somehow ?
Thanks
Martin
Assuming you want to test whether the user's input matches any member of your array, you should do something like this:
NSString *input = textField.text;
BOOL wordFound = NO;
for(NSString *candidate in self.possibleWordsArray) {
if( [input isEqual:candidate] ) {
wordFound = YES;
break;
}
}
if(wordFound) {
...
}
else {
...
}
Notes:
We are comparing the input string against each member of the array in turn. This gives an explicit meaning to the idea of matching a string against an array.
When we find a matching string, we set the flag wordFound to YES and then stop searching (using the break statement). If no match is found, the wordFound flag remains at its original value of NO.
Always use isEqual to test equality between strings, never ==; the later will usually work, but then break occasionally. This is because == only tests whether the two pointers point to the same memory location, whereas you might have two copies of an identical string in different memory locations.