objective-cnsdictionarynsmutabledictionary

BOOL value changing from NO to Yes when setting up from NSDictionary


I have this code

if ([args valueForKey:@"showSetupScreen"]) {
    BOOL showSetupScreen = [args valueForKey:@"showSetupScreen"];
    NSLog(showSetupScreen ? @"YES" : @"NO");
    //  meetingConfig.showSetupScreen = showSetupScreen;
}

Where args is NSMutableDictionary.

args value in my dictionary is NO but when I set to BOOL showSetupScreen = [args valueForKey:@"showSetupScreen"]; it changes into YES

Can someone help me in comprehending why this could be happening.

Attached Screenshot for your reference

enter image description here


Solution

  • A NSDictionary (or NSMutableDictionary) cannot directly contain a primitive C type, such as BOOL. Primitive numeric types (including Boolean) in NSDictionary are wrapped in NSNumber objects. See Numbers Are Represented by Instances of the NSNumber Class and Most Collections Are Objects.

    Thus, use NSNumber method boolValue to extract the Boolean from the NSNumber, e.g.,

    BOOL showSetupScreen = [[args valueForKey:@"showSetupScreen"] boolValue];
    

    Or, more simply:

    BOOL showSetupScreen = [args[@"showSetupScreen"] boolValue];
    

    E.g., examples with primitive C types, including BOOL, NSInteger, and double:

    NSDictionary *args = @{
        @"foo": @NO,
        @"bar": @YES,
        @"baz": @42,
        @"qux": @3.14
    };
    
    BOOL foo = [args[@"foo"] boolValue];         // NO/false
    BOOL bar = [args[@"bar"] boolValue];         // YES/true
    NSInteger baz = [args[@"baz"] integerValue]; // 42
    double qux = [args[@"qux"] doubleValue];     // 3.14
    

    For what it's worth, if you expand the values contained within args, that will show you the internal types for those values, and you will see that that the value associated with showSetupScreen (or foo in my example), is not a BOOL, but rather a pointer to a __NSCFBoolean/NSNumber:

    enter image description here