I have set up one of my core data attributes as a Boolean. Now, I need to set it, but XCode keeps telling me that it may not respond to setUseGPS.
[ride setUseGPS: useGPS.on];
What is the method for setting a boolean in core data? All my other attributes are set this way, and they work great. So, not sure why a boolean does not work to be set this way?
Core Data "does not have" a Boolean type (it does, but it is an NSNumber).
So to set the equivalent of useGPS = YES.
[entity setUseGPS:[NSNumber numberWithBool:YES]];
And the other way around:
BOOL isGPSOn = [[entity useGPS] boolValue];
Update:
As pointed out by SKG, With literals in Objetive-C you can now do it in a simpler way:
[entity setUseGPS:@YES];
BOOL isGPSOn = entity.useGPS.boolValue;
As an alternative approach to the accepted answer, you can simply change the typing from an NSNumber* to a BOOL in the managed object interface definition, such as:
@property (nonatomic) BOOL useGPS; // Notice that the 'retain' is also removed as we're now dealing with a scalar rather than an NSObject
Various alternative approaches are discussed here, but Chris Hanson's response was most illuminating for me, especially:
If you have a numeric attribute
(including a boolean attribute) that's
required, you can just type it as a
scalar instead, and Core Data will do
the right thing:
@property (nonatomic) BOOL isDone;
Even if the attribute is optional,
that'll still work - it'll just
conflate "not present" with "false."
and for a more aligned Cocoa implementation:
One other thing you might want to do
is name the property "done" and just
specify the getter as "isDone." That's
the usual Cocoa naming convention:
@property (nonatomic, getter=isDone)
BOOL done;
Then you can write "if (item.done) {
... }" or "item.done = NO;" and the
compiler will still generate -isDone
for accesses of the property.
Thanks Chris, and hope that this helps someone.
Just to complement @RickiG answer, the way to create a NSNumber
from a Bool
and vice-versa in Swift (at least since v4.2) is:
let nsNumberFromBool = NSNumber(booleanLiteral: true) // or false
let boolFromNSNumber = nsNumberFromBool.boolValue
The "fix" for this (IMHO, it's a bug in Apple's SDK) is to add the following code to your CoreData-generated class. NB: if you do this in a category, in a separate file, then you don't have to re-copy/paste it each time you regenerate the CoreData classes inside Xcode
- (BOOL)useGPS
{
[self willAccessValueForKey:@"useGPS"];
BOOL myuseGPS = [[self primitiveUseGPS] boolValue];
[self didAccessValueForKey:@"useGPS"];
return myuseGPS;
}
- (void)setUseGPS:(BOOL)newValue
{
[self willChangeValueForKey:@"useGPS"];
[self setPrimitiveUseGPS:[NSNumber numberWithBool:newValue]];
[self didChangeValueForKey:@"useGPS"];
}