I'm doing some validation and can't seem to get what should be a simple conditional right
my method has an arg of NSArray and when I NSLog it out I get the following
"var was <null>"
Yet when I do something like the below It always returns YES / TRUE
if (array != nil) {
}
this also fails
if (array != NULL) {
}
Thank you in advance
Sounds like it actually contains [NSNull null]. Plain old nil is logged as (null).
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 am beginning to find my code littered with:
if([p objectForKey#"somekey"] != [NSNull null]) {
}
Is there shorter (character-wise) comparison for NULL?
Background: I am using the SBJson library to parse a JSON string and there are often null values (by design) for some of the keys.
Nothing built-in, but it would be reasonable and simple to create a function MYIsNull() that would do the comparison you want. Just think through what you want to return in the case that the key is missing.
You may want to go the other way and transform -null into nil. For instance, you could add a category on NSDictionary like this:
- (id)my_nonNullObjectForKey:(NSString *)key {
id value = [self objectForKey:key];
if ([value isEqual:[NSNull null]) {
return nil;
}
return value;
}
I would use
if([[p objectForKey#"somekey"] isEqual:[NSNull null]] || ![p objectForKey#"somekey"]) {
// NSNull or nil
} else {
// Stuff exists...Hurray!
}
It seem to work since [NSNull null] is in fact an "object". Hope it helps!
No, you have to test for NSNull. However, if you're finding your code is being littered by it, you might want to create a #define for it.
Bear in mind also that if p is nil, or if p doesn't have a value for someKey, then [p objectForKey#"somekey"] != [NSNull null] evaluates to YES.
So you probably want something like this:
#define IsTruthy(X) ( X && (X != [NSNull null]) )
Is there shorter (character-wise) comparison for NULL?
[NSNull null] is 13 chars. You can say:
NSNull.null // << 11
(id)kCFNull // << 11
Or make a function:
IsNSNull([p objectForKey#"somekey"]) // << 10 in this case and requires no ==, !=
Or (cringes) use a category:
[p objectForKey#"somekey"].mon_isNSNull // << 13 in this case, but requires no ==, !=
Just be careful how you name that category when dealing with nil receivers.
Since you are using SBJSON, you can easily change its code - you have the source.
I have actually modified SBJSON parser to skip [NSNull null] values. They are not added to the dictionaries and when I call objectForKey:, I never get [NSNull null], I just get nil. Then, in most situation I don't even have to check if the value is nil since calling a method on nil usually gives the result I expect.
If you're just worried about the amount of time your taking to type, consider macros:
#define ISNULL(key) [p objectForKey:key] == [NSNull null]
then
if (!ISNULL(#"somekey")) ...
Pretty sure you can just say
if ([p objectForKey:#"somekey"]) {
}
I don't use NSNull much so I'm not 100% sure but I think it tests as false and any other object tests as true.
I'm not exactly sure how to check whether a NSString is blank or not, I've got this code...
NSString *imageName = [myItem objectForKey:#"iconName"];
if(imageName == #"")
{
}
And when I do a print on the myItem object, it comes up as..
iconName = "";
At the NSString *imageName line, I noticed in xcode in the console it says
"variable is not NSString"
Which I don't get as iconName is saved and stored on the parse.com database as a NSString.
When I run that code though it doesn't seem to realise that imageName = "";
You should use this code block when comparing strings:
if ([imageName isEqualToString:#""]){
}
You need to use isEqualToString to compare two strings. If you just use == then you are comparing two pointers.
You could also check to see if the object you are receiving is a NSString by:
if ([imageName isKindOfClass:[NSString class]])
Hope this helps.
Although you have a few answers already, here is my take.
First of all, your warning (not error) can be fixed like this:
NSString *imageName = (NSString *)[myItem objectForKey:#"iconName"];
Then, I would check to make sure that the string is not nil and that it is not blank. The easiest way to do this in objective-C is to check the length of the string, since if it nil it will return 0, and if it is empty, it will return 0:
if([imageName length] == 0)
{
// This is an empty string.
}
As #jlehr points out, if there is the possibility that imageName may not actually be stored as a string, then in order to prevent a crash you need to check first. (This may or may not be needed, depending on the logic of your application):
if ([imageName isKindOfClass:[NSString class]]
{
if([imageName length] == 0)
{
// This is an empty string.
}
}
The "variable is not NSString" is probably because objectForKey: return an id.
To should use [imageName isEqualToString:#""].
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!
}