简体   繁体   中英

typecast BOOL always returns false in iOS 8.1.1

I save & retrive the BOOL value in a dictionary using the following methods.

[userData setObject:@YES forKey:@"IS_AGENT"];

(BOOL) [userData objectForKey:@"IS_AGENT"];

In the above code while retrying the bool value from the dictionary I always get false in the following devices iPhone5s, iPhone5c, iPhone6, iPhone6+ which has iOS 8.1.1 and the same code works fine in iPod Touch which has the same iOS 8.1.1

After googled I came to know that we should not type cast BOOL like this because " BOOL is a char , which is eight bits. If you try to squeeze a value larger than a char through BOOL , the compiler will happily truncate the upper bits, slicing them off."

Now I fixed the issue simply sending boolValue message to a particular object. Check the working code below.

[[userData objectForKey:@"IS_AGENT"] boolValue];

Ok fine.My question is "Why is it happening in a particular devices (iPhone5s,iPhone5c,iPhone5,iPhone6+) only and not in iPod touch which is having the same iOS 8.1.1?"

Here's my speculation what happened before iOS 8.1.1. Maybe Apple changed the way tagged pointers work here, I haven't had an opportunity to test it yet and haven't found any references whether Apple did change something in this system.

You were casting a pointer to a BOOL. Since we're talking about little endian systems here, a pointer like 0x12345678 casted to char yields 0x78, when you cast to BOOL you get 1 since the byte is not 0. On 64-bit iOS systems with 64-bit binaries, the runtime uses tagged pointers .

For tagged pointers, the first byte (which are the least significant digits, we're little endian) will always have the last bit set to mark it as a tagged pointer. If you cast that byte to BOOL you'll always get 1/YES.

But for non-tagged pointers, due to aligning, the last four bits are always 0. And by chance it can happen that the other bits of that are are 0 too (in my tests I've only seen multiples of 0x20 so every 8th object would have 0x00). When you cast that to a BOOL you'll get YES most of the time and sometimes NO.

As you already found out, the correct way to query the value is [[userData objectForKey:@"IS_AGENT"] boolValue] or simply [userData[@"IS_AGENT"] boolValue] if your deployment target is iOS >= 6.

First of all you are using setValue:forKey: and valueForKey: that are KVC methods,
This is strong mistake.

You need to use setObject:forKey: and objectForKey: to write/read objects from NSMutableDictionary .
Also you are casting NSNumber to BOOL , which will have unexpected behavior.

Instead of that code, use

    [userData setObject:@YES forKey:@"IS_AGENT"];
    BOOL isAgent = [[userData objectForKey:@"IS_AGENT"] boolValue];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM