Swift Package for more powerful Enum
types.
Options provides a features to Enum
and OptionSet
types such as:
RawType rawValue
Enum
and OptionSet
typesCodable
OptionSet
Let's say you have Enum
type:
enum ContinuousIntegrationSystem {
case github
case travisci
case circleci
case bitrise
}
We want two things:
OptionSet
so we can store multiple CI sytemsString
If OptionSet
requires an Int
RawType
, how can we parse and store as String
?
With Options we can enable ContinuousIntegrationSystem
to do both:
enum ContinuousIntegrationSystem: Int, MappedValueCollectionRepresented {
case github
case travisci
case circleci
case bitrise
typealias MappedType = String
static let mappedValues = [
"github",
"travisci",
"circleci",
"bitrise"
]
}
typealias ContinuousIntegrationSystemSet = EnumSet<ContinuousIntegrationSystem>
let systems = ContinuousIntegrationSystemSet([.travisci, .github])
Swift Package Manager is Apple's decentralized dependency manager to integrate libraries to your Swift projects. It is now fully integrated with Xcode 11.
To integrate Options into your project using SPM, specify it in your Package.swift file:
let package = Package(
...
dependencies: [
.package(url: "https://github.com/brightdigit/Options", from: "0.1.0")
],
targets: [
.target(
name: "YourTarget",
dependencies: ["Options", ...]),
...
]
)
So let's say we our enum
:
enum ContinuousIntegrationSystem: Int {
case github
case travisci
case circleci
case bitrise
}
We want to be able to make it available as an OptionSet
so it needs an RawType
of Int
.
However we want to decode and encode it via Codable
as a String
.
Options has a protocol MappedValueRepresentable
which allows to do that by implementing it.
enum ContinuousIntegrationSystem: Int, MappedValueRepresentable {
case github
case travisci
case circleci
case bitrise
static func rawValue(basedOn string: String) throws -> Int {
if (string == "github") {
return 0
} else {
...
} else {
throw ...
}
}
static func mappedValue(basedOn rawValue: Int) throws -> String {
if (rawValue == 0) {
return "github"
} else {
...
} else {
throw ...
}
}
}
This can be simplified further by using MappedValueCollectionRepresented
.
By using MappedValueCollectionRepresented
, you can simplify implementing MappedValueRepresentable
:
enum ContinuousIntegrationSystem: Int, MappedValueCollectionRepresented {
case github
case travisci
case circleci
case bitrise
static let mappedValues = [
"github",
"travisci",
"circleci",
"bitrise"
]
}
Now we we've made it simplifies implementing MappedValueRepresentable
so let's look how to use it with Codable
.
So you've setup a MappedValueRepresentable
enum
, the next part is having the MappedType
which in this case is String
the part that's used in Codable
.
This is where MappedEnum
is used:
struct BuildSetup : Codable {
let ci: MappedEnum<ContinuousIntegrationSystem>
}
Now if the String
can be used in encoding and decoding the value rather than the RawType
Int
:
{
"ci" : "github"
}
Next, let's take a look how we could use ContinuousIntegrationSystem
in an OptionSet
.
EnumSet
allows you to interchangeably use Enum
with an OptionSet
. EnumSet
is a Generic struct
while takes any Enum
type with a RawType
. So we can create an OptionSet
instance which uses out ContinuousIntegrationSystem
:
let systems = EnumSet<ContinuousIntegrationSystem>([.travisci, .github])
If your Enum
implements CaseIterable
, then you can extract the individual ContinuousIntegrationSystem
enum values with .array()
:
enum ContinuousIntegrationSystem: Int, CaseIterable {
case github
case travisci
case circleci
case bitrise
}
let systems = EnumSet<ContinuousIntegrationSystem>([.travisci, .github])
print(systems.array())
Lastly, let's put all this together.
If your enum
implements MappedValueRepresentable
and you use it in an EnumSet
, then you can allow for your OptionSet
to be Codable
as an Array
of values rather than the cumulative rawValue
:
enum ContinuousIntegrationSystem: Int, MappedValueCollectionRepresented, CaseIterable {
case github
case travisci
case circleci
case bitrise
static let mappedValues = [
"github",
"travisci",
"circleci",
"bitrise"
]
}
struct BuildSetup : Codable {
let systems: EnumSet<ContinuousIntegrationSystem>
}
let systems = BuildSetup(systems: EnumSet<ContinuousIntegrationSystem>(values: [.travisci, .github]))
For our systems
variable, our Codable
data would be:
{
"systems" : ["travisci", "github"]
}
This will make it easier for making our data human-readable instead of using the rawValue
of 3
.
This code is distributed under the MIT license. See the LICENSE file for more info.
link |
Stars: 19 |
Last commit: 2 weeks ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics