1

Ok. I've searched and searched to no avail and I keep beating my head over this.

I'm trying to determine if a UITextField has a blank value, and if so send a null value up to the server, rather than just a blank string.

The following code

NSDictionary *locationDict = @{
    @"country":countryVal,
    @"state":stateVal,
    @"city":[cityField.text isEqualToString:@""] ? [NSNull null] : cityField.text
};
NSLog(@"%@", locationDict);

logs this

{
    city = "<null>";
    country = US;
    state = TN;
}

I cannot figure out why [NSNull null] gets logged at "<null>". The app keeps sending that string up as the city if the user doesn't enter a value, obviously not what I was going for. I'm not showing the network call here, but I'm using AFNetworking to do this. I can confirm that the dictionary contains that string instead of null before I ever call AFN, though. So I know the problem doesn't lie with AFN.

Any help is greatly appreciated.

Adam Tootle
  • 519
  • 1
  • 6
  • 11

4 Answers4

7

<null> is the result of [[NSNull null] description]. You can see this for yourself with NSLog(@"%@", [NSNull null]);. If you want something other than <null> when the user doesn't enter a city, use the value you want instead of [NSNull null] in your line @"city":[cityField.text isEqualToString:@""] ? [NSNull null] : cityField.text.

SSteve
  • 10,550
  • 5
  • 46
  • 72
  • That makes sense on the description method. I hadn't thought of that. Is there anyway to send a "blank" value, if you will, that isn't some form of NSString? Or is what I'm thinking not even possible? – Adam Tootle Jan 24 '13 at 00:24
  • 1
    Anything in an NSDictionary has to be a descendant of NSObject (hence the requirement of [NSNull null] for a null entry). So you have to decide what will indicate a blank on the server. If you're writing the server code you can interpret `` (or anything you want) as the blank value. If you're not writing the server code, you need to know what the server expects as the representation of a blank value. – SSteve Jan 24 '13 at 00:28
  • Thanks for pointing out the each value needs to be a descendant of NSObject. I got so locked into thinking "I NEED TO PASS NULL" that I was overlooking stuff like that. I think we're going to let the server handle blank strings the way I was thinking a null should be handled. – Adam Tootle Jan 24 '13 at 00:41
2

When you log an Obj-C object (using %@), the NSLog function will actually call -(NSString*)description on it and print whatever string that returns. This method is inherited from NSObject and NSDictionary has overwritten it. It creates a string that is a list of key/value pairs, separated by = and wrapped into curly braces. Therefor it will call description on any key and any value of that dictionary. And if you call description on a NSNull object, it returns the string <null>. The desription method of NSNull looks like this:

- (NSString *)description
{
    return @"<null>";
}

The quotation marks around are added by NSDictionary, since every string that contains characters other than ASCII letters and digits (in this case < and >) is wrapped into quotes. If you replace US by US. and TN by !TN, those two are also in quotes.

What I don't understand is why you use NSNull in the first place. There is no problem to place an empty string into a dictionary and the server could simply check if the string is empty.

NSDictionary *locationDict = @{
    @"country":@"US",
    @"state":@"TN",
    @"city":@""
};
NSLog(@"%@", locationDict);

Output

{
    city = "";
    country = US;
    state = TN;
}
Mecki
  • 125,244
  • 33
  • 244
  • 253
  • Yeah you're right about using NSNull to start with. I got focused on trying to get NSNull to work and I just needed to step back and rethink the whole thing. – Adam Tootle Jan 24 '13 at 00:43
0

The answer about [[NSNull null] description] is correct.

IMO if you want to send a 'null' value to the server, don't populate that key/value pair. If you want anything special done here, you'll have to preprocess the dictionary.

A lot of this depends on whether you have control over how the server handles things and what format you're sending.

It is quite typical to have code that both converts NSNull to nil and back in collection handling code.

xtravar
  • 1,321
  • 11
  • 24
0

If you need a null that describes itself a different way, you might consider subclassing either NSNull or you can subclass NSValue -- subclassing NSValue gives you the added benefit of giving you something that can be decoded/encoded into an NSPropertyList.

iluvcapra
  • 9,436
  • 2
  • 30
  • 32