问题
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?"
回答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.
回答2:
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];
来源:https://stackoverflow.com/questions/27034426/typecast-bool-always-returns-false-in-ios-8-1-1