Swift Tip: Enum Initializers
In Swift Talk 45, we wrote a small library for parsing routes. We represented routes as enums, and added a custom initializer to parse routes:
enum Route {
case home
case users(id: Int)
}
extension Route {
init?(path: String) {
if path == "/" {
self = .home
} else if path.hasPrefix("/users") {
self = .users(id: 1)
} else {
return nil
}
}
}
Of course, this code isn't complete (see the full public episode for that).
Today, we want to focus on assigning to self
inside the initializer. In the initializer of any struct or enum we can treat self
as a mutable variable (as if it were declared using inout
). This is why we can do the following:
enum Result<A> {
case success(A)
case error(Error)
}
extension Result {
init(_ value: A) {
self = .success(value)
}
}
We can even do this in a struct, although it's easier to just call self.init
:
extension UIEdgeInsets {
init(all value: CGFloat) {
self = .init(top: value, left: value, bottom: value, right: value)
}
}
We can also use the same technique if we need a little more flexibility than RawRepresentable
, or if we want to provide a default value:
enum Method {
case post
case get
}
extension Method {
init() {
self = .get
}
init?(_ value: String) {
switch value.lowercased() {
case "post": self = .post
case "get": self = .get
default: return nil
}
}
}
If you enjoyed this tip, check out the episode below, or watch Swift Talk 21: Structs and Mutation for more information on how to work with inout
.
If you'd like to watch all our episodes, you can subscribe ๐
Enjoy!