I have some data stored in an object say objectA. When I print objectA it looks like:
{
employeeId = 1234;
startDate = (null);
endDate = 2013-10-01 04:59:59 +0000;
}
I am storing it in a dictionary as below:
NSDictionary *dict = #{#"employee_id" : objectA.employeeId,
#"start_date" : objectA.startDate,
#"end_date" : objectA.endDate};
I get a crash when I step over the dict code because I am trying to insert a nil object in dict. Error : attempt to insert nil object from objects[1]
Also is this the correct way to pass the date to a dictionary because when I pass this dictionary through isValidJson check, the app crashes again.
Am I doing anything wrong here? How do I handle null/nil check while passing the data to a dictionary?
If your date is nil, either don't include it in that entry in the dictionary (then when you try and read that key you will get back a nil result) or use [NSNull null] as a placeholder object (or whatever null placeholder constant you may want to use - like a specific string #"thisismynullstringconstant") and then when you read your null value from the dictionary convert it to nil.
Related
I'm new to objective c and have been given an existing, outsourced codebase so I apologise if I am missing something very obvious!
I have a Goal data model which I have added a date to:
When making a request to the db for an array of goals, the following is returned:
As you can see, one of the array elements returns an extra KVP which is the date type I added to the xcdatamodel previously. This date refers to the date in which the goal was completed.
When iterating over this array in a for loop and checking whether the date KVP is not nil, NULL is returned for the object in which the date exists for:
([[self.goalArray objectAtIndex:i] valueForKey:#"date"] != nil) ?
[[self.goalArray objectAtIndex:i] valueForKey:#"date"] : [NSNull null]
However, the other values in the object using the same above expression with their keys return their expected values:
It's worth noting that in order to get the app to run, I change the date xcdatamodel to a string value as opposed to date for testing purposes.
I have also added this to the Goal model:
#synthesize date;
...
-(NSDate*) date {
return date;
}
-(void) setDate:(NSDate*)DateTime {
date = DateTime;
}
Is there something obvious I'm missing as I am at a wits end?
Again I apologise if this is a bad question I cannot find any clues as to how to handle objects which may or may not return a certain KVP
You should probably use objectForKey:, that's a NSDictionary function. The valueForKey: basically works on any class and returns a value and/or function result based on the key you pass it.
I can imagine something funky happening when asking for the date.
Your code should probably look somewhat like the following:
NSDictionary *goalInfo = self.goalArray[i];
//goalInfo[#"date"] - This is the short, and more readable version of 'objectForKey:'
if (goalInfo && goalInfo[#"date"]) {
return goalInfo[#"date"];
}
else {
return [NSNull null];
}
I need help.
I want to show data if there is data in dictionary else I want to show No-Data screen if there is no value in dictionary. But problem is like this that I'm getting count as 1. Though there is no value in dictionary.
As you all are trying to guess this one is duplicate. But my question is little-bit different. In this dictionary I have multiple key-value pairs. So I can't find for one key, that's why I'm just trying to get count of it's.
NSLog(#"%lu",(unsigned long)dict.count); //<-- It prints : 1
NSLog(#"%#", dict); //<----It will print below structure with no data
//Output :-
(
{
}
)
So how do I will identify like this dictionary to show it is empty. Though I tried but it is going count as 1.
According to the output dict is not a dictionary ({}), it's an array (()) containing one empty dictionary.
To check if there is a dictionary in the array which is not empty you could use (I renamed dict to array)
if (array.count > 0 && array[0].count > 0) { // will be evaluated to true if the dictionary is not empty
The following code to conditionally concatenate strings for a dictionary seems to work up to the point where I try to place the concatenated result in the dictionary. Can anyone see the error?
NSDictionary *jsonDictionary;
NSString* dictString = #"#\"first\":first,#\"last"
NSString *dictString2=dictString;
if (date.length>0&&![date isKindOfClass:[NSNull class]]) {
//only include this key value pair if the value is not missing
dictString2 = [NSString stringWithFormat:#"%#%s", dictString, "#\"date\":date"];
}
jsonDictionary = #{dictString2}; //syntax error. Says expected colon but that does not fix anything
The syntax for creating an NSDictionary using object literals is:
dictionary = #{key:value}
(and optionally, it can contain multiple key/value pairs separated by commas, but never mind that right now.)
Where "key" and "value" are both NSObjects.
Your line that is throwing the error only contains 1 thing. The contents of a the string in dictString2 has nothing to do with it.
It looks to me like you are trying to build a JSON string manually. Don't do that. Use NSJSONSerialization. That class has a method dataWithJSONObject that takes an NSObject as input and returns NSData containing the JSON string. That's how you should be creating JSON output.
Creating an NSDictionary with values that may be null:
NSDictionary *dict = #{
#"key" : value ?: [NSNull null],
};
When serializing a dictionary, NSNulls are translated to null in the JSON.
If you want to exclude such keys completely, instead of having them with a null value, you'll have to do more work. The simplest is to use an NSMutableDictionary and test each value before adding it.
I have a NSMutableDictionary.
NSMutableDictionary * dict = #{
#"0" : #"car",
#"1" : #"ball",
#"2" : #"plane",
}
At one point, by error, I was assigning a nil to to an element on a dictionary. For example:
dict[#"1"] = nil;
for my surprise, instead of crash, the element "1" is being deleted.
Is this something recent? a sanctioned feature or a bug? I wonder if this is a feature, because I always used something like
[dict removeObjectForKey:#"1"];
To remove objects from dictionaries.
I never knew it was possible. Perhaps Apple is making Objective-C similar to Swift.
I just verified the behavior in Swift 2.0.
var dict: NSMutableDictionary = [ "0" : "car", "1" : "ball", "2" : "plane" ];
dict["1"] = nil
print("\(dict)")
It must to be a bug because it contradicts the documentation.
From NSMutableDictionary Class Reference:
- setObject:forKeyedSubscript:
Adds a given key-value pair to the dictionary.
Declaration
OBJECTIVE-C
- (void)setObject:(ObjectType)object
forKeyedSubscript:(id)aKey
Parameters
object
The value for aKey. A strong reference to the object is maintained by the dictionary.
IMPORTANT
Raises an NSInvalidArgumentException if anObject is nil. If you need to represent a nil value in the dictionary, use NSNull.
aKey
The key for value. The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol). If aKey already exists in the dictionary, anObject takes its place.
IMPORTANT
Raises an NSInvalidArgumentException if aKey is nil.
UPDATE: 2016-04-21
Apple has updated it's documentation! passing a nil value can be used to delete a key.
object
The value for aKey. A strong reference to the object is maintained by the dictionary.
Passing nil will cause any object corresponding to aKey to be removed from the dictionary.
There are different APIs to add an object to a mutable dictionary and they behave differently when you pass nil:
setObject:forKeyedSubscript: (a.k.a dict[key] = nil) and setValue:forKey: accept nil and in that case they will remove the object associated corresponding to that key.
setObject:forKey: will raise an exception if nil is passed
All this is documented in https://developer.apple.com/documentation/foundation/nsmutabledictionary
arrdata=[[NSMutableArray alloc]initWithObjects:strname,strWeb,strAdd,strPhone,strrate, nil];
[arrAllData addObject:arrdata];
I fetched data from a webservice. in my condition if strweb has no value then it simply ignores other values like stradd,sphone and strrate. How can I solve this problem?
you can do like this in a simplest way.
if(strweb==nil)
{
strweb=#"null";
}
Note: pass null in <> bracket;
Try this code,
if(strWeb == nil){
strWeb = [NSString stringWithFormat:#"%#", [NSNull null]];
}
arrdata=[[NSMutableArray alloc]initWithObjects:strname,strWeb,strAdd,strPhone,strrate, nil];
[arrAllData addObject:arrdata];
When your any object nil while creation time of array then your array will be end with than object and remaining objects will discards. That why you need to check every object should not be nil according above code stuff then add it into array.
If strWeb is nil then your array structure will be
arrdata=[[NSMutableArray alloc]initWithObjects:strname,nil]; future object will discard.,strAdd,strPhone,strrate,
output of arrdata containg only one object strname
Other way,
Set any default value if your string is nil. for example,
if(strWeb == nil){
strWeb = #"This Value is discarded"; // It could be anything identifier for your purpose.
}
arrdata=[[NSMutableArray alloc]initWithObjects:strname,strWeb,strAdd,strPhone,strrate, nil];
[arrAllData addObject:arrdata];
While retrieving time you can match above string with value inside the object.
You use the initializer -initWithObjects:. As you know the object list is terminated with nil. If one of the references has the value nil, -initWithObjects: thinks that this is the terminator.
Check the references (i. e. strweb). If it is nil, assign a default value to it or do not encounter the variable in the list.