TANASCHITA.COM

# How to solve problems with bitwise operators in Swift

## Learn to use the power of bitwise operations and option sets in iOS.

The server sends an integer value between `0` and `127` that represents the state of a weekdays selection. When the server sends a `0`, no checkbox should be selected. For a `127`, all check boxes should be selected. The numbers in between represent all the other states. The task was to evaluate this value to be able to preselect the appropriate checkboxes.

The logic behind the integer value is simple when we imagine that each weekday is represented by it's bit value:

``````mon tue wed thu fri sat sun

0000000 - equals 0 - no weekday is selected
0000011 - equals 3 - sat sun are selected
1010101 - equals 85 - mon wed fri sun are selected
1111100 - equals 124 - mon tue wed thu fri are selected
1111111 - equals 127 - all days are selected
``````

With this pattern, we are able to represent every state of the seven check boxes with numbers ranging from 0 to 127.

So, how do we convert the number send by the server into the correct checkboxes state?

### The trivial solution

The first approach that might come to our mind could look like this:

``````switch weekdaysSelectionValue {
case 0:
monCheckbox.isChecked = false
tueCheckbox.isChecked = false
wedCheckbox.isChecked = false
thuCheckbox.isChecked = false
friCheckbox.isChecked = false
satCheckbox.isChecked = false
sunCheckbox.isChecked = false
case 1:
monCheckbox.isChecked = false
tueCheckbox.isChecked = false
wedCheckbox.isChecked = false
thuCheckbox.isChecked = false
friCheckbox.isChecked = false
satCheckbox.isChecked = false
sunCheckbox.isChecked = true
.
.
.
case 127:
monCheckbox.isChecked = true
tueCheckbox.isChecked = true
wedCheckbox.isChecked = true
thuCheckbox.isChecked = true
friCheckbox.isChecked = true
satCheckbox.isChecked = true
sunCheckbox.isChecked = true
}
``````

Having 127 switch cases is a lot of fun, but let's look into a more generic approach to solve this with bitwise operators.

``````monCheckbox.isChecked = // get the bit on the 6th position & check if it is 0 or 1
tueCheckbox.isChecked = // get the bit on the 5th position & check if it is 0 or 1
wedCheckbox.isChecked = // get the bit on the 4th position & check if it is 0 or 1
thuCheckbox.isChecked = // get the bit on the 3th position & check if it is 0 or 1
friCheckbox.isChecked = // get the bit on the 2th position & check if it is 0 or 1
satCheckbox.isChecked = // get the bit on the 1th position & check if it is 0 or 1
sunCheckbox.isChecked = // get the bit on the 0th position & check if it is 0 or 1
``````

To implement the solution above, let's look into how to work with bits in Swift.

### Basics about bits in Swift

A bit is the smallest piece of information that can be 1 or 0. Eight bits together are called a byte. The unsigned `UInt8` type in Swift is represented by 8 bits, that means we can represent 2⁸ = 256 different numbers with `UInt8` which is enough for us since we only need 127 numbers.

``````UInt8

0 = 00000000 = 0 * 2^0
1 = 00000001 = 1 * 2^0
2 = 00000010 = 0 * 2^0 + 1 * 2^1
3 = 00000011 = 1 * 2^0 + 1 * 2^1
...
6 = 00000110 = 1 * 2^0 + 1 * 2^1 + 1 * 2^2
...
255 = 11111111 = 1 * 2^0 + 1 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6
``````

A signed `Int8` type also represents 256 different numbers, but ranging from -128 to 127, since the most left bit is used to signify whether the integer is positive or negative. So theoretically, we could also use an `Int8` for our task.

In Swift, when defining a number, we can choose to write down it's bit representation:

``````let value1: UInt8 = 3
let value2: UInt8 = 0b00000011
``````

In the example above, `value1` and `value2` are the same values, they are just written down differently. We could use basic operators on them like we are used to:

``````let value3 = 3 + 0b00000011 // 6
let value4 = 3 - 0b00000011 // 0
``````

### Bitwise shifting and bitwise operators in Swift

``````0b00000011 | 0b00000101 // The bitwise OR operator produces 0b00000111
0b00000011 & 0b00000101 // The bitwise AND operator produces 0b00000001
0b00000010 << 1 // The bitwise LEFT SHIFT operator << produces 0b0000100
0b00000010 >> 1 // The bitwise RIGHT SHIFT operator >> produces 0b0000001
``````
• the OR operator `|` produces a `0` only if both bits are a `0`. Otherwise it produces a `1`.
• the AND operator `&` produces a `1` only if both bits are a `1`. Otherwise it produces a `0`.
• the LEFT SHIFT operator `<<` shifts every bit to the left by a certain number of places. Any bits that are moved beyond the bounds are discarded.
• the RIGHT SHIFT operator `>>` does the same as the LEFT SHIFT operator in the other direction.

We can solve our task with the operators above. If you are interested in more of those operators, you can check out the official documentation.

### The solution with bitwise operators

With the help of those operators, we now can do the following.

``````monCheckbox.isChecked = ((serverValue & 0b01000000) >> 6) == 1
tueCheckbox.isChecked = ((serverValue & 0b00100000) >> 5) == 1
wedCheckbox.isChecked = ((serverValue & 0b00010000) >> 4) == 1
thuCheckbox.isChecked = ((serverValue & 0b00001000) >> 3) == 1
friCheckbox.isChecked = ((serverValue & 0b00000100) >> 2) == 1
satCheckbox.isChecked = ((serverValue & 0b00000010) >> 1) == 1
sunCheckbox.isChecked = ((serverValue & 0b00000001) >> 0) == 1
``````

What exactly is happening here? Let's pick one value to illustrate this.

1. Imagine, we get a `85` from the server. That is a `0b01010101` as bit representation.

2. Now, we want to know if the Friday's checkbox is checked. For that, we nullify all bits instead of the one on position `2` by using the AND operator.

``````0b01010101 & 0b00000100 // produces 0b000000100
``````

3. Next, we want to know if the value on the second position is a `1` or a `0`. For that, we shift `2` positions to the left, so the value is now at position `0`.

``````0b000000100 >> 2 // produces 0b000000001
``````

4. Finally, we can check if our produced value is a `0` or a `1` with the basic `==` operator.

``````0b000000001 == 1 // is true
``````

Actually, we can even solve this without shifting. Instead of shifting to the right and checking if the value is `1`, we can simply check if our value is not `0`:

``````friCheckbox.isChecked = serverValue & 0b00000100 != 0
``````

### The solution with OptionSet

Now that we understand how to solve the task with bitwise operators, there is even a simpler solution. The Swift standard library offers the `OptionSet` that represents bit set types, where every bit represents a member of the set.

``````struct WeekdayOptions: OptionSet {
let rawValue: Int

static let sun = WeekdayOptions(rawValue: 1 << 0)
static let sat = WeekdayOptions(rawValue: 1 << 1)
static let fri = WeekdayOptions(rawValue: 1 << 2)
static let thu = WeekdayOptions(rawValue: 1 << 3)
static let wed = WeekdayOptions(rawValue: 1 << 4)
static let tue = WeekdayOptions(rawValue: 1 << 5)
static let mon = WeekdayOptions(rawValue: 1 << 6)
}
``````

After defining our weekday options as an `OptionSet`, we get all the logic behind it for free. To check if Monday is selected, we now can simply use the `OptionSet`'s `contains` method.

``````let weekdayOptions = WeekdayOptions(rawValue: serverValue)
monCheckbox.isSelected = weekdayOptions.contains(.mon)
``````

Even though an `OptionSet` makes it easy, knowing the bit operators and how it works behind the scenes makes it's usage more clear.

Of course, an `OptionSet` offers a lot more useful methods. You can check them out in the official documentation.