Daniel G. Wilson
Daniel G. Wilson

Reputation: 15055

Boolean as a property in Cocoa

I'm sure that this has been asked MANY times before, but it's still giving me trouble. I define my class's Boolean property like this:

@property(readwrite,assign) BOOL namesVisible;

And it doesn't give compiler errors, but it NSLogs as (null). Obviously I'm doing something wrong here, but I'm at a loss to what it is.

Upvotes: 3

Views: 3497

Answers (2)

Peter Hosey
Peter Hosey

Reputation: 96363

Because you're trying to log it as an object by using %@, and a BOOL isn't an object, and your property's value is NO and you're lucky.

The last part is because you're only passing a BOOL to NSLog, but since your format string says to expect an object pointer, it will read a pointer's worth from the argument stack. Since a pointer is bigger than a BOOL, it's reading more than you passed it. You're lucky that it got zeroes for all four/eight bytes (your NO was only one of them); the result is that it sent its description message to nil, which returned nil for the description string, which prints as “(null)” in the output.

If you'd been unlucky and/or the property's value had been YES, it would have read something that isn't nil, but is nonetheless probably not a pointer to an object that exists. As such, trying to log that would cause a crash, probably of the EXC_BAD_ACCESS variety. If you'd been unlucky and lucky at the same time, you would have printed the description of an actual object, and wondered how the hell your BOOL looked like that.

The solution is one of two things:

NSLog(@"My Boolean property: %d", (int)[myObject myBooleanProperty]);

or:

NSLog(@"My Boolean property: %@", [myObject myBooleanProperty] ? @"YES" : @"NO");

The former casts the Boolean value to a full-size int and prints that value as such (most probably either 0 or 1), whereas the latter will pass either @"YES" or @"NO" as the argument depending on the Boolean value. Since NSString literals are (NSString) objects, the %@ formatter becomes the right one.

Upvotes: 2

Ben Gottlieb
Ben Gottlieb

Reputation: 85542

BOOLs are just chars, either 0 or 1. As such, you don't need to use a storage keyword in the property declaration, so it should be:

@property (readwrite) BOOL namesVisible;

Second, when logging a BOOL, use the int format string, %d, or pass in a string:

NSLog(@"My Boolean: %d, or %@", object.namesVisible, object.namesVisible ? @"Yes" : @"No");

Upvotes: 8

Related Questions