Swift
NS_OPTIONS
Bitmask
Enumerations
Swift Programming

How to create NS_OPTIONS-style bitmask enumerations in Swift?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Swift, the modern replacement for Objective-C NS_OPTIONS is OptionSet. It gives you the same bitmask-style behavior while keeping the code type-safe and readable, so you can represent combinations of flags without falling back to raw integer constants.

Define an OptionSet

Here is the standard pattern:

swift
1struct DisplayOptions: OptionSet {
2    let rawValue: Int
3
4    static let showTitle = DisplayOptions(rawValue: 1 << 0)
5    static let showSubtitle = DisplayOptions(rawValue: 1 << 1)
6    static let showIcon = DisplayOptions(rawValue: 1 << 2)
7}

Each option gets one bit. That is exactly the same mental model as NS_OPTIONS.

Use Multiple Flags Together

Once defined, options can be combined naturally:

swift
1let options: DisplayOptions = [.showTitle, .showIcon]
2
3if options.contains(.showTitle) {
4    print("title enabled")
5}
6
7if options.contains(.showSubtitle) {
8    print("subtitle enabled")
9}

This is much clearer than manually checking integer bitmasks everywhere.

Why OptionSet Is Better Than a Plain Enum

A normal Swift enum represents one case at a time. Bitmask options are different because you often need several values simultaneously.

For example:

  • 'showTitle'
  • 'showIcon'

can both be active together. That is why OptionSet is the right abstraction and a plain enum is not.

Raw Value Type Choices

You can back an OptionSet with different integer types depending on your needs:

swift
1struct Permissions: OptionSet {
2    let rawValue: UInt8
3
4    static let read = Permissions(rawValue: 1 << 0)
5    static let write = Permissions(rawValue: 1 << 1)
6    static let execute = Permissions(rawValue: 1 << 2)
7}

For most app code, Int is fine. If you are bridging with C or matching a specific storage layout, choosing an explicit unsigned integer type can make the intent clearer.

A Bridging Example

If you are replacing old Objective-C code like:

objective-c
1typedef NS_OPTIONS(NSUInteger, DisplayOptions) {
2    DisplayOptionsShowTitle = 1 << 0,
3    DisplayOptionsShowSubtitle = 1 << 1,
4    DisplayOptionsShowIcon = 1 << 2
5};

the Swift OptionSet version is the intended equivalent.

Add Convenience Groups

You can define grouped options too:

swift
extension DisplayOptions {
    static let all: DisplayOptions = [.showTitle, .showSubtitle, .showIcon]
}

That is useful when a group of flags appears repeatedly in your code.

You also get set-like operations for free, such as union and intersection, which makes option manipulation feel much more natural than hand-writing bitwise expressions everywhere.

Common Operations You Will Actually Use

OptionSet is nice because normal code reads like intent rather than math:

swift
1var current: DisplayOptions = [.showTitle, .showIcon]
2
3current.insert(.showSubtitle)
4current.remove(.showIcon)
5
6let important: DisplayOptions = [.showTitle, .showSubtitle]
7let overlap = current.intersection(important)
8
9print(current.contains(.showSubtitle))
10print(overlap == important)

Those APIs make maintenance easier than raw & and | operators, especially once multiple developers touch the codebase.

Interoperability Notes

If you are calling Apple APIs or Objective-C code that historically used NS_OPTIONS, Swift will usually expose those values as an OptionSet already. Matching that style in your own APIs keeps your code consistent with the rest of the platform and makes call sites feel familiar to Swift developers.

Common Pitfalls

  • Using a regular enum when the requirement is actually a combinable set of flags.
  • Reusing the same bit for more than one option.
  • Falling back to raw integer checks everywhere instead of using contains.
  • Forgetting that OptionSet values can represent multiple active options at once.

Summary

  • Swift uses OptionSet as the NS_OPTIONS-style bitmask pattern.
  • Each option should have a unique bit in rawValue.
  • 'OptionSet allows clean combination and membership checks.'
  • It is the correct Swift abstraction for flag-style options.
  • Use it whenever multiple enum-like values must be active simultaneously.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.