Core Data predicate not matching boolean attribute - ios

I have an NSManagedObject subclass with a boolean attribute. It's non-optional, with NO as the default. In the model interface it is declared as #property (nonatomic, retain) NSNumber * deleted;, in the implementation, #dynamic deleted;.
It is persisting correctly if I check the underlying SQLite file. However, I am finding that fetches with predicates querying this attribute do not work correctly. I have tried deleted == YES, deleted == %# with #YES and [NSNumber numberWithBool:YES], and indeed deleted == 1. I've even tried using a single equals sign out of pure voodoo paranoia. Nothing works.
This is causing a bug in my code using an NSFetchedResultsController. The full predicate is currently (list = %#) OR (deleted = YES). I change deleted to #YES, change the value of list, and the controller issues an unexpected NSFetchedResultsChangeDelete, despite the object still logically matching the predicate.
There's no doubting it doesn't match the predicate however (at least in memory), as I've tested with:
BOOL matchesBefore = [self.fetchedResultsController.fetchRequest.predicate evaluateWithObject:thing];
// do stuff, setting thing.deleted = #YES, thing.list = #"something else"
BOOL matchesAfter = [self.fetchedResultsController.fetchRequest.predicate evaluateWithObject:thing];
NSAssert(matchesBefore && matchesAfter, #"Should still match");
Interestingly, in the debugger, the attribute is displayed as deleted = 0;, however printing the actual NSNumber yields (NSNumber *) $5 = 0x07455ec0 1. Again, in the underlying database, the value is stored correctly as '1'.
So I'm greatly confused. Any ideas? This is iOS, on 5.x both in the simulator and on device.

Sounds like a collision with reserved names, some deep lying undocumented (?) use of the keyword deleted. (Wouldn't be strange in the context of a NSManagedObject, or maybe in NSFetchedResultsController.) Try to change the name of the field to something else.

Related

Merge two objects of same type

I have two objects:
deviceConfigInfo and deviceStatusInfo
Both contain an array of devices (so theres a third device object actually).
For each device returned in deviceConfigInfo there are these properties:
uuid
name
somethingElse
lookAnotherOne
and for deviceStatusInfo
uuid
name
somethingElse
someStatusInfo
someMoreStuff
(If you hadn't guessed, I just made up some random properties)
So back to that third object I mentioned, device, I created it with all the properties combined. Now, my question is, say the deviceStatusInfo gets updated, how can I update the device object without losing the "old" data that isn't overwritten (in this case, the lookAnotherOne property).
Does it have to be a manual process of getting the device with the matching uuid and then updating each of the properties for deviceStatusInfo or is there a quicker way of doing this? Imagine there were loads of properties.
Hopefully this makes sense. If it helps, I am using Mantle to create the objects/models.
I noticed that Mantle has the following function which I was able to use:
mergeValueForKey:fromModel:
So in my device model, I added two functions:
mergeConfigInfoKeysFromModel:
mergeStatusInfoKeysFromModel:
These functions have access to an array that contains NSString values representing the properties/keys. There is one array for the configInfo and another for statusInfo properties/keys.
I then loop through the keys and use valueForKey to check it has an actual value. If it does, I then call the mergeValueForKey:fromModel:.
Example Code:
- (void)mergeConfigInfoKeysFromModel:(MTLModel *)model
{
NSArray *configInfoKeys = #[#"uuid", #"name", #"somethingElse", #"lookAnotherOne"];
for (NSString *key in configInfoKeys) {
if ([model valueForKey:key]) {
[self mergeValueForKey:key fromModel:model];
}
}
}
All I have to do now, is call the appropriate merge function on the device object when I get an update, passing over the updated device object. Just as below:
[self.device mergeConfigInfoKeysFromModel:deviceUpdate];

IOS Upgrade to 7.0 Issue With Dictionary Lookup

Using location Manager in an app the following code worked prior to iOS7, now with iOS7, I'm getting the "??" escape. I'm looking up the state to retrieve the state abbreviation. The location mananger is properly retrieving the State (if I code to use "state" it will give me the desired state), but the lookup to the plist file (set to dictionary object) to get the abbreviation, for whatever reason fails and gives the "??" option. Any Ideas what's up?
NSString *state = placemark.administrativeArea;
NSString *stateAbbreviation = [self.usStateAbbreviations objectForKey:[state uppercaseString]];
NSString *stateTarget = state;
if (stateAbbreviation) {
stateTarget = stateAbbreviation;
}else{
stateTarget = #"??";
}
From another question:
For iOS6 i get the full name of the administrative area (ex.
"California"), but for the iOS7, I get the value of "CA".
So, it would seem, that state is already the stateAbbreviation on iOS7, so the key is different and you don't get a result for:
[self.usStateAbbreviations objectForKey:[state uppercaseString]];
According to Apple's documentation for CLPlacemark:
The string in this property can be either the spelled out name of the
administrative area or its designated abbreviation, if one exists. If
the placemark location is Apple’s headquarters, for example, the value
for this property would be the string “CA” or “California”.
So there doesn't seem to be a guarantee, one way or the other.

NSNumber in NSDictionary is always null

I'm building a project and want to add a NSNumber into a NSDictionary. But the it crashed because of the null value. So, I created another small program to check what happened. As you can see in the snapshot: Why the the value of NSNumber in NSDictionary is null?
I've run your code and I could reproduce the problem. But it seems like a debugger problem. For instance, if after your dictionary is created, go to the console and try printing the dictionary.
po dictionary
My result is like:
$4 = 0x2083e770 {
number = 1;
}
So it's not null at all. Also, after that, anum is assigned correctly and b is set to YES. So it really looks like a debugger issue instead of a bug from you.

If Statement Failing sometimes with id BoolValue Comparison?

I am pulling data from the web that is formatted in JSON and when I parse the data using "ValueForKeyPath" it stores the string value as an id object.
So I store the data into a NSMutableArray
In the debugger window it shows all the elements added as (id) null.
I have an if statement
if ([[self.activeCategories objectAtIndex:selected] boolValue] == true)
Sometimes I would say 20% of the time it fails the if statement when it should not.
I was wondering if it was because the self.activeCategories is storing id types. Do I need to do [NSString stringWithFormat#"%#", x] to all the objects inside the array? It seems like when I just straight cast it by using (NSString *) it is still type id in the debugger.
It's a very strange error to me... as the error is not consistently reproducible.
Try it like that:
if ([[self.activeCategories objectAtIndex:selected] boolValue])
According to that article a BOOL may hold values other than 0 and 1 which may fail the comparison.

Core Data: odd crash when getting data from store

Hia, got a one to many relation for chars and items. one char can hold a specific item, same item can be used by others.
The CharInfo is defined as follows:
#property (nonatomic, retain) ItemInfo * slotEar;
CharInfo.slotEar is a reference to the item. It is optional, min count 1, max count 1 and delete rule Nulify.
ItemInfo is defined as:
#property (nonatomic, retain) NSSet* slotEar;
ItemInfo.slotEar is a reference to the char. It is optional, one to many and delete rule Nulify.
They are referencing to each other.
There is an additional class that works with the data. It does hold the reference as well and provide it for storing.
ItemInfo *slotEar;
CharInfo get created before saving like this:
When I save the CharInfo, I set the ItemInfo (from my structure) in the aproviate slot.
CharInfo *charInfo = [NSEntityDescription
insertNewObjectForEntityForName:#"CharInfo"
inManagedObjectContext:managedObjectContext];
charInfo.slotEar = currentChar.slotEar;
Saving the context works.
When I try to load the CharInfo from store, it works most of the time from now. After relaunching he does crash at this line.
curentChar.slotEar = charInfo.slotEar;
If there was no item reference (nil) then all is fine.
Unfortunately the crash is more a halt. No error is given, he just stops at that line in the debugger and the green description next to the link says: EXC_BAD_ACCESS
Seems something is wrong with the reference I save or the way how I try to take it from the CharInfo to my class. Any idea?
Screenshot added:
No bug with core data or the worker class ivars, but with an int array with 6 ints filled with 100 ints.

Resources