How can I check if an object in an NSArray is NSNu

2020-02-17 04:01发布

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

9条回答
走好不送
2楼-- · 2020-02-17 04:32

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

查看更多
放荡不羁爱自由
3楼-- · 2020-02-17 04:32

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
}
查看更多
Emotional °昔
4楼-- · 2020-02-17 04:36

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.
} 
查看更多
Explosion°爆炸
5楼-- · 2020-02-17 04:39

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.

查看更多
淡お忘
6楼-- · 2020-02-17 04:41
id object = myArray[0];// similar to [myArray objectAtIndex:0]

if(![object isEqual:[NSNull null]])
{
    //do something if object is not equals to [NSNull null]
}
查看更多
再贱就再见
7楼-- · 2020-02-17 04:45

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.

查看更多
登录 后发表回答