71

I am getting an array with null value. Please check the structure of my array below:

 (
    "< null>"
 )

When I'm trying to access index 0 its crashing because of

-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70

Currently its crashing because of that array with a crash log:

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70'
*** First throw call stack:
(0x2d9fdf53 0x3820a6af 0x2da018e7 0x2da001d3 0x2d94f598 0x1dee57 0x1dfd31 0x302f598d 0x301a03e3 0x3052aeed 0x3016728b 0x301659d3 0x3019ec41 0x3019e5e7 0x30173a25 0x30172221 0x2d9c918b 0x2d9c865b 0x2d9c6e4f 0x2d931ce7 0x2d931acb 0x3262c283 0x301d3a41 0xabb71 0xabaf8)
libc++abi.dylib: terminating with uncaught exception of type NSException
JAL
  • 41,701
  • 23
  • 172
  • 300
Navi
  • 1,696
  • 2
  • 17
  • 36

9 Answers9

127
id object = myArray[0];// similar to [myArray objectAtIndex:0]

if(![object isEqual:[NSNull null]])
{
    //do something if object is not equals to [NSNull null]
}
Charith Nidarsha
  • 4,195
  • 3
  • 28
  • 32
  • 2
    if you want to check for NSString use [object isKindOfClass:[NSString class]] before calling [object isEqualToString:]; – Charith Nidarsha Sep 27 '13 at 20:22
  • ok i got the answer,now am adding only good values to array rejecting all un necesary nulls..lol thanks alot – Navi Sep 27 '13 at 20:24
  • 1
    No, don't use isEqual. For example if object in this case is a UIPrintPaper object, you'll get an exception because its isEqual implementation sends the NSNull class an unexpected selector. – xaphod Mar 19 '17 at 18:30
  • 1
    if `myArray` does equal to `NSNull`, `myArray[0]` will crash? – Kesong Xie Aug 15 '17 at 00:35
31
if (myArray != (id)[NSNull null])

OR

if(![myArray isKindOfClass:[NSNull class]]) 
Antonio Netto
  • 564
  • 4
  • 10
14

Building off of Toni's answer I made a macro.

#define isNSNull(value) [value isKindOfClass:[NSNull class]]

Then to use it

if (isNSNull(dict[@"key"])) ...
respectTheCode
  • 42,348
  • 18
  • 73
  • 86
9

Awww, guys. This is an easy one.

// if no null values have been returned.
if ([myValue class] == [NSNull class]) {
    myValue = nil;
}

I'm sure there are better answers, but this one works.

Alex Zavatone
  • 4,106
  • 36
  • 54
7

I found the code for working with NSNull has the following problems:

  • Looks noisy and ugly.
  • Time consuming.
  • Error prone.

So I created the following category:

@interface NSObject (NSNullUnwrapping)

/**
* Unwraps NSNull to nil, if the object is NSNull, otherwise returns the object.
*/
- (id)zz_valueOrNil;

@end

With the implementation:

@implementation NSObject (NSNullUnwrapping)

- (id)zz_valueOrNil
{
    return self;
}

@end

@implementation NSNull (NSNullUnwrapping)

- (id)zz_valueOrNil
{
    return nil;
}

@end

It works by the following rules:

  • If a category is declared twice for the same Class (ie singleton instance of the Class type) then behavior is undefined. However, a method declared in a subclass is allowed to override a category method in its super-class.

This allows for more terse code:

[site setValue:[resultSet[@"main_contact"] zz_valueOrNil] forKey:@"mainContact"];

. . as opposed to having extra lines to check for NSNull. The zz_ prefix looks a little ugly but is there for safety to avoid namespace collisions.

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
  • 2
    @gnasher729 Ha ha, up to you ;) – Jasper Blues Apr 17 '15 at 07:13
  • 1
    The problem with this is that even though it is clever, it's not clear how it works to someone who is not you unless you comment it heavily and then people get used to it. Every cycle developers spend thinking, "Whhhat?," are cycles they aren't spending solving problems. – Alex Zavatone Feb 01 '17 at 15:38
  • Is it better to create one category that encapsulates the complexity, or have each developer write their own style of boiler-plate, error-prone code? Spending cycles solving the same problem over and over? The documentation for that method only requires a few lines. Provides something similar to how optional types work in other languages. Personally i like avoid ugly error prone, noisy nested if blocks, however if it works better in your context to write them out then do so. – Jasper Blues Feb 01 '17 at 23:50
4

You can use the following check:

if (myArray[0] != [NSNull null]) {
    // Do your thing here
}

The reason for this can be found on Apple's official docs:

Using NSNull

The NSNull class defines a singleton object you use to represent null values in situations where nil is prohibited as a value (typically in a collection object such as an array or a dictionary).

NSNull *nullValue = [NSNull null];
NSArray *arrayWithNull = @[nullValue];
NSLog(@"arrayWithNull: %@", arrayWithNull);
// Output: "arrayWithNull: (<null>)"

It is important to appreciate that the NSNull instance is semantically different from NO or false—these both represent a logical value; the NSNull instance represents the absence of a value. The NSNull instance is semantically equivalent to nil, however it is also important to appreciate that it is not equal to nil. To test for a null object value, you must therefore make a direct object comparison.

id aValue = [arrayWithNull objectAtIndex:0];
if (aValue == nil) {
    NSLog(@"equals nil");
}
else if (aValue == [NSNull null]) {
    NSLog(@"equals NSNull instance");
    if ([aValue isEqual:nil]) {
        NSLog(@"isEqual:nil");
    }
}
// Output: "equals NSNull instance"

Taken from https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/NumbersandValues/Articles/Null.html

Marky
  • 1,294
  • 1
  • 18
  • 40
3

A lot of good and interesting answers have been given already and (nealry) all of them work.

Just for completion (and the fun of it):

[NSNull null] is documented to return a singleton. Therefore

if (ob == [NSNull null]) {...} 

works fine too.

However, as this is an exception I don't think that using == for comparing objects is a good idea in general. (If I'd review your code, I'd certainly comment on this).

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
2

In Swift (or bridging from Objective-C), it is possible to have NSNull and nil in an array of optionals. NSArrays can only contain objects and will never have nil, but may have NSNull. A Swift array of Any? types may contain nil, however.

let myArray: [Any?] = [nil, NSNull()] // [nil, {{NSObject}}], or [nil, <null>]

To check against NSNull, use is to check an object's type. This process is the same for Swift arrays and NSArray objects:

for obj in myArray {
    if obj is NSNull {
        // object is of type NSNull
    } else {
        // object is not of type NSNull
    }
}

You can also use an if let or guard to check if your object can be casted to NSNull:

guard let _ = obj as? NSNull else {
    // obj is not NSNull
    continue;
}

or

if let _ = obj as? NSNull {
    // obj is NSNull
}
JAL
  • 41,701
  • 23
  • 172
  • 300
2

Consider this approach:

Option 1:

NSString *str = array[0];

if ( str != (id)[NSNull null] && str.length > 0 {
    // you have a valid string.
} 

Option 2:

NSString *str = array[0];
str = str == (id)[NSNull null]? nil : str;

if (str.length > 0) {
   // you have a valid string.
} 
Wayne
  • 3,359
  • 3
  • 30
  • 50