Reputation: 1044
I'm having some trouble accessing a parameter that is passed with an enum.
Generic RequestType, more will be included.
enum RequestType {
case flagging(api : FlaggingRequestType)
}
Here is my enum that accepts another FlaggingRequestType (another enum that accepts a string parameter)
enum FlaggingRequestType {
case getFlag(api : String)
}
protocol Requestable {
var requestType : RequestType { get set }
}
Here I build my flagging request
let flaggingRequest = RequestBuilder.buildFlaggingRequest(flagRequest: .getFlag(api: "http://www.apiworld.com"))
Here is my method to actually sends the request from another method.
func sendRequest(for apiRequest : Requestable) {
switch apiRequest.requestType {
case .flagging:
self.flaggingAPI(for: apiRequest)
}
}
The problem is I can't figure out how to access the value passed in the api
parameter found in apiRequest
/ flaggingRequest
. Is this possible? I hope this is clear :)
Upvotes: 20
Views: 34696
Reputation: 414
Since it is nested, you will have to do nested switch cases, like this:
switch apiRequest {
case .flagging(let value):
switch value {
case .getFlag(let api):
print(api) // api is the string passed in the associated value
break
}
break
}
UPDATE
Swift has changed the behaviour around switch statements, so cases are no longer falling through to the next case. This means you no longer need to explicitly break
. Instead, if you want the old behaviour, you can use the fallthrough
keyword, to make your execution continue into the next case.
You can also unwrap cases in the outer switch:
switch apiRequest {
case .flagging(.getFlag(let api)):
print(api) // api is the string passed in the associated value
}
Upvotes: 6
Reputation: 1
In Swift UI
enum Action {
case INCREMENT
case DECREMENT
}
struct ContentView: View {
@State var counter = 0
var body: some View {
HStack {
Button(action: {
handleIncreaseDecrease(action: Action.DECREMENT)
}) {
Text("-")
}
Text("\(counter)")
Button(action: {
handleIncreaseDecrease(action: Action.INCREMENT)
}) {
Text("+")
}
}
}
func handleIncreaseDecrease(action:Action) {
if (action == Action.INCREMENT) {
counter += 1
} else {
counter -= 1
}
}
}
Upvotes: -1
Reputation: 73206
case .one(.two(let val))
If, for a given instance of a type that conforms to Requestable
, your single goal is to access the associated String
value of the "inner" FlaggingRequestType
instance (for a known inner case
), you can use nested pattern matching and binding in a single case
, e.g. used not only in a switch
buy, say, an if
statement.
// your example setup
enum FlaggingRequestType {
case getFlag(api : String)
}
protocol Requestable {
var requestType : RequestType { get set }
}
enum RequestType {
case flagging(api : FlaggingRequestType)
}
// dummy type conforming to 'Requestable'
struct Foo : Requestable {
var requestType: RequestType =
.flagging(api: .getFlag(api: "http://www.apiworld.com"))
}
// Q: how to find the nested "http://www.apiworld.com" String
// from a 'Foo' instance?
let foo = Foo()
// A: use nested pattern matching, e.g. in a single 'if' statement
if case .flagging(.getFlag(let api)) = foo.requestType {
print(api) // http://www.apiworld.com
}
You can naturally make use of the nested pattern matching also in the cases of a switch
statement:
switch foo.requestType {
case .flagging(.getFlag(let api)): print(api) // http://www.apiworld.com
// ...
default : () // in non-exhaustive pattern matching above
}
In case the associated value of different types of the FlaggingRequestType
are of the same type, and also the same expected usage, this nested binding can be a useful alternative to several nested switch
statements. E.g., if extending the example setup above to:
enum FlaggingRequestType {
case getFlag(api : String)
case getHandle(api : String)
case getId(id: Int)
}
We could apply nested pattern matching in a single switch
statement, where one single case
could cover binding associated values for several different cases of the inner enum, given that those associated values have the same type.
switch foo.requestType {
case .flagging(.getFlag(let api)),
.flagging(.getHandle(let api)): print(api) // api is 'String', a flag or a handle
case .flagging(.getId(let id)): print(id) // id is 'Int'
// ...
default : () // in case of non-exhaustive pattern matching above
}
Finally, note that you might want to consider using type constrained generics for your sendRequest
method, rather than typing out a protocol to be used as type.
func sendRequest<T: Requestable>(for apiRequest : T) { /* ... */ }
Upvotes: 8
Reputation: 5694
Here's a great link for enums with associated values https://appventure.me/2015/10/17/advanced-practical-enum-examples/#sec-1-5
func sendRequest(for apiRequest : Requestable) {
switch apiRequest.requestType {
case .flagging(let api):
// access api value here
self.flaggingAPI(for: apiRequest)
}
}
Upvotes: 29