Initial value of a Core Data Entities properties? - iphone

I have several core data entities that contains a bunch of empty NSString properties.
I parse some XML and set the properties I can get a hold of and would like to set the "empty" ones to "n/a" as in "not available". So if my XML does not contain the values it sort of tidy up the Entity by giving it a "n/a" string I can test for later on, also should one of these make it to a UILabel it will not display (null) .. which leads me to my question:
I do this to test if the property on the Entity is already sat, is nil or is empty:
for(NSString *s in allPossibleStrings) {
if([[f valueForKey:s] isKindOfClass:[NSString class]] && [[f valueForKey:s] isEqualToString:#""]) {
[f setValue:#"n/a" forKey:s];
}
if ([[f valueForKey:s] isKindOfClass:[NSString class]] && [f valueForKey:s] == nil) {
[f setValue:#"n/a" forKey:s];
}
}
It turns out however that I still end up with a lot of values being displayed as (null).
So I was thinking can the property be something else than #"" empty or (nil)
I believe the NSManagedObject should be KVC compliant so I did a test where I copied my NSManagedObject property by property, only difference is that is is a subclass of just NSObject instead of NSManagedObject.
Sadly this behaves in the exact same way. It also leaves values as (null)
Hope someone can pick up on where I go wrong with these string tests :)
Thank You

You could set the default property value of your entity to "N/A" (that's a good practice, because you might want to use sqlite for iPhone app shipping, and it doesn't work well with null values because sqlite and cocoa don't have the same vision of "null") and set "optional" to "No".
if([[f valueForKey:s] isKindOfClass:[NSString class]] && [[f valueForKey:s] isEqualToString:#"NA"]) {
//Tell your program to know that it's null if it needs to know
}
Cheers

What is allPossibleStrings? You could do this to get to all the properties:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyEntityName" inManagedObjectContext:moc];
for (NSString *attr in [entity attributesByName]) {
[object setValue:#"n/a" forKey:attr];
}

The issue is that when something is nil, what you can get back from any managed object property (not just strings) is an NSNull object. So if you check also for isKindOfClass:[NSNull class] I think your code will do what you want.

Related

Find Existence of Key in NSDictionary

How can we identify the object is available for a particular key. I have tried following:
for(NSDictionary *item in jsonArray){
if([item objectForKey:#"EventDate"])
NSLog([item objectForKey:#"EventDate"]);
}
This is getting crash the code with error:
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x6a567b0
I have also find many posts that is showing objectForKey will return nil if a key doesn't exists. Than my question is there is also a method in NSDictionary class that is "setNilValueForKey". How is this possible that we cannot specify the NSDictionary key with nil object and also we have the method to set nil value for object in NSDictionary.
Please Suggest on first and also make me clear on second query.
1) Your jsonArray contains other types of objects than NSDictionaries, including at least one NSString. NSString doesn't respond to objectForKey: so it throws an exception when you try to call it. You'll have to look at the JSON to determine how to proceed with whatever you were doing.
2) There is an NSObject method setNilValueForKey: which is related to key-value coding. This isn't really related to NSDictionary. If you really need to represent nil in your dictionary, set [NSNull null] as the object for your key that represents nil.
Hope this helps!
Not all the objects in your array are dictionaries. You need to check what kind of data you're processing before you work on it. Something like this:
for(NSObject* item in jsonArray) {
if ([item isKindOfClass:[NSDictionary class]]) {
// do dictionary stuff
}
else if ([item isKindOfClass:[NSString class]]) {
// do string stuff
}
}
item is not a NSDictionary its a String. So check your jsonArray it may be contains only strings not dictinaries
Answer to second query
There is a non-nil object called NSNull that is built specifically to represent nils in situations where "plain" nil is not acceptable. If you replace your nils with [NSNull null] object, NSDictionary will take them. You would need to check for NSNull on the way out, though.
Refer more here
Answer to first query
for(id *item in jsonArray)
{
if([item isKindofClass:[NSDictionary class])
{
NSArray *allKeys = [item allKeys];
for(NSString *strKey in allKeys)
{
if([strKey isEqualToString:#"EventDate"])
{
// EventDate key has object
NSLog([item objectForKey:#"EventDate"]);
}
}
}
}

NSMutableArray lastObject not working in UITableView iPhone?

I want to get the last object from an NSMutableArray. When I use the code below to get the last object from the NSMutableArray it is not finding it:
if ([mutableArray lastObject])
{
NSLog(#"Last Object");
}
else
{
NSLog(#"Not a Last Object");
}
When ever I call this code the if statement is only calling for every objects from an array. Can anyone please help me to solve this?
[mutableArray lastObject] returns an id typed object which is the last object of your array. it is not a test.
To see it you should write something like :
id myLastObject = [mutableArray lastObject];
NSLog(#"my last object is : %#",myLastObject);
edit :
What do you mean by check last object ?
checking equality with the isEqual method checks if both objects are same objects, meaning only one object but you might wanna check if two objects have same properties, thus checking if properties have same values.
if ([someObject isEqual:[mutableArray lastObject]]) {
NSLog(#"Last Object");
}

objectForKey string with "/" crashes my app

Following code works fine:
NSDictionary *item;
if([arrTesting count] >0 )
item = [arrTesting objectAtIndex:0];
// The text "article" is what I'm searching for to ensure it exists
if([item objectForKey:#"article"] != [NSNull null])
{
NSString *mid = [[item objectForKey:#"article"] objectForKey:#"id"];
(more code below...)
But if I replace "article" with "/code/location/article" the app crashes. What gives?? What am I missing??
If a NSDictionary does not contain a specific element, objectForKey: will return nil and not [NSNull null].
So, if the dictionary does not contain the object that you are looking for, you are essentially doing a comparison like nil != [NSNull null] which will always evaluate to true. This is probably not what you want.
(Checking for NSNull means that the entry is there, but has a null value. This is common for for example JSON responses. I am not sure if it is common in your scenario though.)

Best way to check for variable's class in objective C?

I have an object which I am not sure is an NSString or not (could be NSNull, for example when reading a json into an NSDictionary) and I would like to get an NSString* if it is a valid string, nil otherwise.
Is there an accepted way of doing this except writing my own function?
+(NSString*)stringWithMaybeString:(id)maybeString {
if ( [maybeString isKindOfClass:[NSString class]] )
return maybeString;
return nil;
}
Your method looks like the accepted way of doing this to me :)
Possibly you could add it to NSString using a category.

how to add nil to nsmutablearray?

NSArray *array = [[NSArray alloc] initWithObjects:#"ΕΛΤΑ",
#"ΕΛΤΑ COURIER", #"ACS", #"ACS ΕΞΩΤΕΡΙΚΟ",
#"DHL", #"INTERATTICA", #"SPEEDEX",
#"UPS", #"ΓΕΝΙΚΗ ΤΑΧΥΔΡΟΜΙΚΗ", #"ΜΕΤΑΦΟΡΙΚΕΣ ΕΞΩΤΕΡΙΚΟΥ", nil];
This is working because it has nil at the end.
But I add objects like this: addObject:name etc...
So at the end I have to add nil I do this addObhect:nil but when I run the app it still crashes at cellForRowAtIndexPath:
how can I do this work?
Ok, I dont have to add nil
What is the reason that my app crashes then?
If you must add a nil object to a collection, use the NSNull class:
The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
Assuming "array" is of type NSMutableArray:
....
[array addObject:[NSNumber numberWithInt:2];
[array addObject:#"string"];
[array addObject:[NSNull null]];
You don't need to call [addObject:nil]
The nil in initWithObjects: is only there to tell the method where the list ends, because of how C varargs work. When you add objects one-by-one with addObject: you don't need to add a nil.
You can't add nil when you're calling addObject.
If you really want a Null-ish item in your collection, NSNull is there for that.
You need to add NSNull class and the best way to do it is like this:
NSArray *array = #[ #"string", #42, [NSNull null] ];
I personally recommend to use a specific value like 0 instead of null or nil in your design of your code, but sometimes you need to add null.
There is a good explanation from this Apple reference.
nil is used to terminate the array
nil is not an object that you can add to an array: An array cannot contain nil. This is why addObject:nil crashes.
pass your object through this method when adding to array to avoid attempt to insert nil object from objects crashes.
-(id) returnNullIfNil:(id) obj {
return (obj == nil) ? ([NSNull null]) : (obj);
}
[NSNull null] returns an null object which represents nil.
You can't add an object to an NSArray because that class is immutable. You have to use NSMutableArray if you want to change the array after it is created.