For a simple element type, pros & cons
struct Model {
let id: String
let title: String
…
}
func changes(from lhs: Model, to rhs: Model) -> Parts { … }
let changedParts = changes(from: …, to: …)
// things of interest
changedParts.contains(.id) // reload all
changedParts.isSubset(of: [.title]) // just update the text view
changedParts.isEmpty // ignore
// OptionSet
struct Parts: OptionSet { // one single type
let rawValue: Int
public static let id: Self = Parts1(rawValue: 1 << 0)
public static let title: Self = Parts1(rawValue: 1 << 1)
init(rawValue: Int) {
self.rawValue = rawValue
}
}
// Set<Enum>
typealias Parts = Set<Part> // two types needed, inner Part, and outer Set
enum Part { // nice to read
case id
case title
}
func doSomething(with parts: Parts) { … }
// OptionSet
doSomething(with: .id) // less brackets
doSomething(with: .title)
doSomething(with: [])
doSomething(with: [.id])
doSomething(with: [.title])
doSomething(with: [.id, .title])
Parts.id.formUnion(.title) // compound and set type are the same, this is simpler than Set<…>
// Set<Enum>
doSomething(with: [])
doSomething(with: [.id])
doSomething(with: [.title])
doSomething(with: [.id, .title])
[Part.id].formUnion([.title])
Otherwise they both behave like Set.
Since OptionSet is based on a single Int
and bit masks, performance should be better. (depends a lot on usage if relevant)
let id: Parts = .id
let mixed: Parts =
// OptionSet
print(Parts.id) // "Parts(rawValue: 1)"
print([.id, .title] as Parts) // "Parts(rawValue: 3)" <- useless
// Set<Enum>
print(Part.id) // "id"
print([.id, .title]) // "[Part.id, Part.title]" <- nicer
print([.id, .title]) // "[MyModule.Scope.Part.id, MyModule.Scope.Part.title]" can get long when from a different module and nested
// OptionSet
extension Parts {
static var allCases: [.id, .title] // Need to add custom code that lists all options
}
// Set<Enum>
enum Parts: CaseIterable { … } // `.allCases` is automatically generated
- Set cannot be bridged to ObjC NSSet, because Enums are not objects.
- (NS)OptionSet can be declared in ObjC instead of Swift aswell and then used from both, or the rawValue can be passed around
- Codable if enum is Codable. Set will encode as Array. If used for persistence, need to pay attention that enum rawValues are stable.
- OptionSet will encode a single
rawValue
. If used for persistence, need to pay attention that rawValues are stable.
- OptionSet cannot gain sub-detail per case
- In Set, the enum can in the future receive associated Values, but this changes a lot (no longer CaseIterable etc) and is probably a different use case