Jirune
Jirune

Reputation: 2340

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?"

Upvotes: 1

Views: 627

Answers (2)

DarkDust
DarkDust

Reputation: 92316

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.

Upvotes: 3

l0gg3r
l0gg3r

Reputation: 8954

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];

Upvotes: 1

Related Questions