# How to solve problems with bitwise operators in Swift

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

updated on 29 Apr 2024 · 8 min read

Knowing how to work with bitwise operators can become really useful when solving specific types of problems.

Let's directly jump in and look at an example.

Recently, I had to solve the following task at work.

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 sun0000000 - equals 0 - no weekday is selected0000011 - equals 3 - sat sun are selected1010101 - equals 85 - mon wed fri sun are selected1111100 - equals 124 - mon tue wed thu fri are selected1111111 - 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.

Now, the question is:

*What is the best approach to convert the number send by the server into the correct checkboxes state?*

### The trivial solution

The most trivial approach which might come to our mind could look as follows:

switch weekdaysSelectionValue {case 0:monCheckbox.isChecked = falsetueCheckbox.isChecked = falsewedCheckbox.isChecked = falsethuCheckbox.isChecked = falsefriCheckbox.isChecked = falsesatCheckbox.isChecked = falsesunCheckbox.isChecked = falsecase 1:monCheckbox.isChecked = falsetueCheckbox.isChecked = falsewedCheckbox.isChecked = falsethuCheckbox.isChecked = falsefriCheckbox.isChecked = falsesatCheckbox.isChecked = falsesunCheckbox.isChecked = true...case 127:monCheckbox.isChecked = truetueCheckbox.isChecked = truewedCheckbox.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 1tueCheckbox.isChecked = // get the bit on the 5th position & check if it is 0 or 1wedCheckbox.isChecked = // get the bit on the 4th position & check if it is 0 or 1thuCheckbox.isChecked = // get the bit on the 3th position & check if it is 0 or 1friCheckbox.isChecked = // get the bit on the 2th position & check if it is 0 or 1satCheckbox.isChecked = // get the bit on the 1th position & check if it is 0 or 1sunCheckbox.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 - which means we can represent 2⁸ = 256 different numbers with UInt8. That's enough for our use case since we only need 127 numbers.

UInt80 = 00000000 = 0 * 2^01 = 00000001 = 1 * 2^02 = 00000010 = 0 * 2^0 + 1 * 2^13 = 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. 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 use its bit representation:

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

In the example above, value1 and value2 are the same values, they are just written down differently.

### Bitwise shifting and bitwise operators in Swift

Additionally to basic operators, Swift offers advanced operators for bit manipulations, for example:

0b00000011 | 0b00000101 // The bitwise OR operator produces 0b000001110b00000011 & 0b00000101 // The bitwise AND operator produces 0b000000010b00000010 << 1 // The bitwise LEFT SHIFT operator << produces 0b00001000b00000010 >> 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.

### Solution with bitwise operators

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

monCheckbox.isChecked = ((serverValue & 0b01000000) >> 6) == 1tueCheckbox.isChecked = ((serverValue & 0b00100000) >> 5) == 1wedCheckbox.isChecked = ((serverValue & 0b00010000) >> 4) == 1thuCheckbox.isChecked = ((serverValue & 0b00001000) >> 3) == 1friCheckbox.isChecked = ((serverValue & 0b00000100) >> 2) == 1satCheckbox.isChecked = ((serverValue & 0b00000010) >> 1) == 1sunCheckbox.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.

**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 right, 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

### Solution with an OptionSet

Now, since we understand how to solve this task with bitwise operators, there is an even simpler solution. Swift's standard library offers an OptionSet type which represents bit set types.

struct WeekdayOptions: OptionSet {let rawValue: Intstatic 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 weekday options as an OptionSet as shown above, we get all the logic behind it for free. To check if Monday is selected, we 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 its usage more clear.

Newsletter

Like to support my work?

Say hi

Related tags

Articles with related topics

Latest articles and tips