Well my code was like this:
I have two strings, place and date. I am using them like this:
cell.datePlace.text= [NSString stringWithFormat:#"%#, %#",date,place];
In some entries, the output is like this:
"21/10/2012, <null>"
"21/11/2012, None"
"21/12/2013, London"
My app does not crash but I want the place to be visible only when is not null and not equal to None.
So I tried this:
NSString * place=[photo objectForKey:#"place"];
if ([place isEqualToString:#"None"]) {
cell.datePlace.text= [NSString stringWithFormat:#"%#",date];
} else {
cell.datePlace.text= [NSString stringWithFormat:#"%#, %#",date,place];
}
Problem was when place was <null> my app crashed and I got this error:
[NSNull isEqualToString:] unrecognized selector send to instance
So, i tried this:
if (place) {
if ([place isEqualToString:#"None"]) {
cell.datePlace.text= [NSString stringWithFormat:#"%#",date];
} else {
cell.datePlace.text= [NSString stringWithFormat:#"%#, %#",date,place];
}
} else {
cell.datePlace.text= [NSString stringWithFormat:#"%#",date];
}
But the problem remains.
I guess your source data is coming from JSON or similar (something where data is being parsed in and missing data is being set to NSNull). It's the NSNull that you need to deal with and aren't currently.
Basically:
if (place == nil || [place isEqual:[NSNull null]]) {
// handle the place not being available
} else {
// handle the place being available
}
Use
if (! [place isKindOfClass:[NSNull class]) {
...
}
instead of
if (place) {
...
}
Note: NSNull object is not nil, so the if (place) will be true then.
Use [NSNull null]:
if ([place isKindOfClass:[NSNull class]])
{
// What happen if place is null
}
Related
When parsing API responses, sometimes I can not rely on strings being embedded in quotation marks. ID's are a good example of this, where some API's will send the numerical ID as a string while some will send it as a number.
What is a good practice when parsing such a value? If I simply parse it to an NSString like so:
NSString *myID = (NSString *)message["myID"];
I can end up with an NSString object that somehow contains (long)123.
And using stringValue would cause issues when the value is actually already sent as a string (since NSString does not have a stringValue function).
A way that works, but is somewhat ugly, is this:
id myID = (NSString *)message["myID"];
if ([myID respondsToSelector:#selector(stringValue)])
{
myID = [myID stringValue];
}
You could do something like:
id myID = message["myID"];
if ([myID isKindOfClass:[NSString class]]) { ... }
else { ... }
As long as this logic is encapsulated inside data parser and is opaque for your api users (i.e. they will always get a string) any approach is fine, e.g.:
- (NSString*)parseID:(NSDictionary*)message {
id rawID = message["myID"];
if ([rawID isKindOfClass:[NSString class]]){
return rawID;
} else if ([rawID isKindOfClass:[NSNumber class]]) {
return [(NSNumber*)rawID stringValue];
} else {
// We might still want to handle this case.
NSAssert(false, #"Unexpected id type");
return nil;
}
}
Alternative is to define stringValue in extension, so any possible objet will respond to selector:
#implementation NSString(JSONStringParsing)
- (NSString *)stringValue {
return [self copy];
}
#end
Why not just use description?
NSArray *objects = #[
#NSIntegerMin,
#NSIntegerMax,
#"123456789"
];
for (id object in objects) {
NSString *stringObject = [object description];
NSLog(#"%# -> %# | %#", [object className], [stringObject className], stringObject);
}
I am getting a Json from server by making a network request in my app.I am getting <null> value for some keys in Json object.My app gets crashed if this type of response is received.Please tell me how can i validate>?
I have tried this but it does not work all time.
if(!(user_post.username==(id)[NSNull null]) )
{
user_post.username=[dict_user_info objectForKey:#"name"];
if(user_post.username!=nil)
{
ser_post.username=[dict_user_info objectForKey:#"name"];
}
else
{
user_post.username=#"Username";
}
}
Consider testing the value for null so your program won't crash. Like this:
if([dict_user_info objectForKey:#"name"] != [NSNull null])
{
ser_post.username=[dict_user_info objectForKey:#"name"];
}
Create a Category of NSDictionary and add following method in it, which replaces null value with empty string for each key in dictionary.
- (NSDictionary *)dictionaryByReplacingNullsWithStrings
{
const NSMutableDictionary *replaced = [self mutableCopy];
const id nul = [NSNull null];
const NSString *blank = #"";
for(NSString *key in self) {
const id object = [self objectForKey:key];
if(object == nul || object == NULL) {
//pointer comparison is way faster than -isKindOfClass:
//since [NSNull null] is a singleton, they'll all point to the same
//location in memory.
[replaced setObject:blank
forKey:key];
}
}
return [replaced copy];
}
Usage :
[yourJSONDictionary dictionaryByReplacingNullsWithStrings];
Read more about Category in iOS Tutorial 1 and Tutorial 2
yourJsonObject = [myDic valueforkey#"key"];
if(yourJsonObject != [NSNull null])
{
//not null
}
** you can also check whether object exist or not
if(yourJsonObject)
{
//exist
}
I think you've confused your logic. I am trying to stay true to your code, but let me know if the following is not what you intended:
if (dict_user_info[#"name"] != nil && [dict_user_info[#"name"] isKindOfClass:[NSNull class]] == NO) {
user_post.username = dict_user_info[#"name"];
if (user_post.username != nil) {
ser_post.username = user_post.username;
} else {
user_post.username = #"Username";
}
}
These are a couple of methods I wrote for my projects, try them :
/*!
* #brief Makes sure the object is not NSNull or NSCFNumber, if YES, converts them to NSString
* #discussion Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON and expect it to be an NSString, pass it through this method just to make sure thats the case.
* #param str The object that is supposed to be a string
* #return The object cleaned of unacceptable values
*/
+ (NSString *)cleanedJsonString:(id)str
{
NSString *formattedstr;
formattedstr = (str == [NSNull null]) ? #"" : str;
if ([str isKindOfClass:[NSNumber class]]) {
NSNumber *num = (NSNumber*) str;
formattedstr = [NSString stringWithFormat:#"%#",num];
}
return formattedstr;
}
/*!
* #brief Makes Sure the object is not NSNull
* #param obj Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON ( NSArray, NSDictionary or NSString), pass it through this method just to make sure thats the case.
* #return The object cleaned of unacceptable values
*/
+ (id)cleanedObject:(id)obj
{
return (obj == [NSNull null]) ? nil : obj;
}
/*!
* #brief A JSON cleaning function for NSArray Objects.
* #discussion Sometimes JSON responses can contain NSNull objects, which does not play well with Obj-C. So when you access a value from a JSON and expect it to be an NSArray, pass it through this method just to make sure thats the case. This method first checks if the object itself is NSNull. If not, then it traverses the array objects and cleans them too.
* #param arr The Objects thats supposed to be an NSArray
* #return The NSNull Cleaned object
*/
+ (NSArray *)cleanedJsonArray:(id)arr
{
if (arr == [NSNull null]) {
return [[NSArray alloc] init];
}
else
{
NSMutableArray *arrM = [(NSArray*)arr mutableCopy];
int i=0;
for (id __strong orb in arrM)
{
if (orb == [NSNull null])
{
[arrM removeObjectAtIndex:i];;
}
i++;
}
return arrM;
}
}
Just pass a JSON string, array or object to the appropriate method and the method will clean it for you.
Do yourself a favour and write a method that handles this and put it into an extension. Like
- (NSString*)jsonStringForKey:(NSString*)key
{
id result = self [key];
if (result == nil || result == [NSNull null]) return nil;
if ([result isKindOfClass:[NSString class]]) return result;
NSLog (#"Key %#: Expected string, got %#", key, result);
return nil;
}
You might even add some code that accepts NSNumber* results and turns them into strings, if that is what your server returns (some poster here had the problem that his server returned dress sizes as numbers like 40 or strings like "40-42" which makes something like this useful).
And then your code becomes one readable line
user_post.username = [dict_user_info jsonStringForKey:#"name"] ?: #"username";
I actually use several slightly different methods depending on whether I expect null, expect no value, expect an empty string or not, which gives me warnings when my assumptions are wrong (but always returns something that doesn't break).
try this:
if(!(user_post.username == (NSString *)[NSNull null]) )
When I print the following I get (null)
NSLog(#"%#", [[responseObject objectAtIndex:i] objectForKey:#"child"]);
Now I want to do a validation to check if it returns (null). How am I supposed to do this?
I tried the following but it doesn't work:
1.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqualToString:#"(null)"]) {
}
2.
if (![[[responseObject objectAtIndex:i] objectForKey:#"child"] isEqual:#"(null)"]) {
}
"null" isn't just a NSString. You should do some research into the concept of a null object.
What you're looking for can be written like this:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
//key "child" not in dictionary
}
(null) is the representation of nil displayed by NSLog.
You can write the following:
if ([[responseObject objectAtIndex:i] objectForKey:#"child"] == nil) {
}
Or a shorter alternative:
if (![[responseObject objectAtIndex:i] objectForKey:#"child"]) {
}
Another way to check is to use string length. I know other answers are just as good, I am just giving OP and anyone else in future some more options.
NSString *childStr = [[responseObject objectAtIndex:i]objectForKey:#"child"];
if ([childStr length] < 1)
{
//no value specified - childStr is NULL
}
else
{
//there is something in the childStr - throw a party!
}
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"hello"]) {
NSLog(#"only if not null show %#",[defaults objectForKey:#"hello"]);
}
This is a way to check it from User Defaults. It will only print if the saved object does not equal null.
This question already has answers here:
How to detect if NSString is null?
(5 answers)
Closed 8 years ago.
I'm new to iOS development. I get an error when I compare NSString with NSString nil value. It is not working in if condition.
my code is:
NSDictionary *responseFromJSON = [JSON objectForKey:#"response"];
NSString *strResponseMsg = [responseFromJSON objectForKey:#"104"];
if ([strResponseMsg isEqualToString:nil])
{
NSLog(#"login Invalid");
}
else
{
NSLog(#"login success");
}
You can simply do like this,
NSString * string = nil;
if (string!=nil && // not nil, means 0x0 object
string.length>0 && // at leaset one character should exists
[string isEqual:[NSNull null]]) { // to avoid 'null' in string
// valid string
}
You can do like this,
if ([yourString isEqual:[NSNull null]])
{
//your code goes here
}
Hope this helps.
Use below
NSString *strResponseMsg = [responseFromJSON objectForKey:#"104"];
if (!strResponseMsg)
{
NSLog(#"login Invalid");
}
else
{
NSLog(#"login success");
}
If you want to check the NSString whether it's nil or empty.
You just need to do something like that:
if (strResponseMsg.length) {}
Because it will not go inside if the strResponseMsg is nil or empty. It will only go inside when strResponseMsg is not nil and no empty.
how can I check if this exists?:
[[dataArray objectAtIndex:indexPathSet.row] valueForKey:#"SetEntries"]
I want to know whether this key exists or not. How can I do that?
Thank you very much :)
EDIT:
dataArray has Objects in it. And these objects are NSDictionaries.
I presume that [dataArray objectAtIndex:indexPathSet.row] is returning an NSDictionary, in which case you can simply check the result of valueForKey against nil.
For example:
if ([[dataArray objectAtIndex:indexPathSet.row] valueForKey:#"SetEntries"] != nil) {
// The key existed...
}
else {
// No joy...
}
So I know you already selected an answer, but I found this to be rather useful as a category on NSDictionary. You start getting into efficiency at this point with all these different answers. Meh...6 of 1...
- (BOOL)containsKey: (NSString *)key {
BOOL retVal = 0;
NSArray *allKeys = [self allKeys];
retVal = [allKeys containsObject:key];
return retVal;
}
Check if it's nil:
if ([[dataArray objectAtIndex:indexPathSet.row] valueForKey:#"SetEntries"] != nil) {
// SetEntries exists in this dict
} else {
// No SetEntries in this dict
}
this also works using Objective-C literals using the following syntax:
NSDictionary *dict = #{ #"key1" : #"value1", #"key2" : #"value2" };
if (dict[#"key2"])
NSLog(#"Exists");
else
NSLog(#"Does not exist");
Try this:
if ([dict objectForKey:#"bla"]) {
// use obj
} else {
// Do something else like create the object
}
This one does the same but with less code:
if (dataArray[indexPathSet.row][#"SetEntries"] != nil) { /* the key exists */ }
else { /* the key doesn't exist */ }
if ((NSNull *)[[dataArray objectAtIndex:indexPathSet.row] valueForKey:#"SetEntries"] != nil) {
// SetEntries exists in this dict
} else {
// No SetEntries in this dict
}
That's the right answer.
Check dictionary contains any value. I prefer [dic allKeys].count > 0 to check.
Use the (unsigned long) option:
if ( (unsigned long)[[dataArray objectAtIndex:indexPathSet.row] valueForKey:#"SetEntries"] ) {
// Key exist;
}else{
// Key not exist;
};