How to check for null value in NSNumber

2019-02-13 22:08发布

First off I confess my ignorance, I've learned everything I know about Objective-C in the few months I've been working on my project. I also find it utterly frustrating how Objective-C seems to complicate what would be simple matters in any other language I've worked with. This question is a case in point...

In the first run my app downloads a bunch of JSON which it uses to populate a CoreData store. I use an Obj-C/JSON library (CJSONDeserializer) to convert the JSON to NSArrays. In the JSON download for one CoreData entity there's a field containing a number ("show_id":2) identifying the related field in another entity if there is one or null ("show_id":null) otherwise. In processing that field I assign it to an NSNumber using...

NSNumber *shoIndex = [[item objectForKey:typeKey] objectForKey:@"show_id"];

I then try to check that I have a valid number before attempting to fetch & link the related record so as to not do wasteful processing where there is no related record.

Interrogating shoIndex with...

NSLog(@"shoIndex: %i, %@, %@", shoIndex, shoIndex, [shoIndex description]);

Gives...

shoIndex: 19590600, <null>, <null>

where the JSON value was null &...

shoIndex: 228300880, 51, 51

otherwise.

So far the only successful check I've made is with...

if (![[shoIndex description] isEqualToString:@"<null>"]) {

Can anyone suggest a better way?

Update...

Looking at it another way shoIndex is assigned as a NSNumber that sometimes contains a NSString value @"<null>". Does Obj-C have something like an isa operator that I could use to check the type of the contents of shoIndex?

TIA, Pedro.

3条回答
贪生不怕死
2楼-- · 2019-02-13 22:43

In some cases, such as missing keys in NSUserDefaults, you get back the literal @"" as an empty string.

Here's my safe check for an NSNumber.

Note the check for it being an NSNumber occurs first because NSNumber doesn't understand isEqualToString

        id savedPin = [[NSUserDefaults standardUserDefaults] valueForKey:@"blah"];  // don't assume is created so don't type as NSNumber*
        if ( ![savedPin isKindOfClass:[NSNumber class]] && [savedPin isEqualToString:@""]) {  
查看更多
地球回转人心会变
3楼-- · 2019-02-13 22:48

Use [shoObject class] to get the class of an object; so, to test shoObject's class, you would use

[shoObject isKindOfClass:[NSString class]];

Once you've sorted out what markers define an empty string or NSNumber, you can create a macro. I do with this by keeping an IsEmpty macro in a file called CommonMacros.h. Here's the code:

//Thanks Wil
//http://wilshipley.com/blog/2005/10/pimp-my-code-interlude-free-code.html

static inline BOOL IsEmpty(id thing) {
    return thing == nil
    || ([thing isEqual:[NSNull null]]) //JS addition for coredata
    || ([thing respondsToSelector:@selector(length)]
        && [(NSData *)thing length] == 0)
    || ([thing respondsToSelector:@selector(count)]
        && [(NSArray *)thing count] == 0);
}

Then, after importing CommonMacros.h, you can call the function like this:

if (IsEmpty(shotIndex)) {
    //do stuff
}

This should take care of this problem, and will also work on strings, arrays, etc, as you can see from the code. Thanks to Wil Shipley!

查看更多
▲ chillily
4楼-- · 2019-02-13 22:59

In Objective-c, it's nil not null. So:

if (shotIndex != nil) {
   // its not nil
}
查看更多
登录 后发表回答