Enum of tuples in Swift
It depends what you mean by "similar". What I do is use a Struct with static constant properties:
struct Trouble {
static let Generic_Error = (0, "Unknown")
static let DB_Error = (909, "Database")
}
Now things like Trouble.Generic_Error
are usable throughout your code.
Is it possible to put a tuple in an enum with Swift?
As pointed out by @MartinR. Also, according to Apple docs, "enumeration cases can specify associated values of any type to be stored along with each different case value". If you want to keep using enum
, you may need to do something like:
static func PrintFruit(fruit:FruitTuple.Apple)
{
let shape:String = fruit.shape
let colour:String = fruit.colour
print("Fruit is \(shape) and \(colour)")
}
I'm not certain of what you want, but I guess using typealias
could help achieve your goal.
typealias FruitTuple = (shape: String, colour: String)
enum Fruit
{
static let apple = FruitTuple("round" , "red")
static let orange = FruitTuple("round", "orange")
static let banana = FruitTuple("long", "yellow")
}
func printFruit(fruitTuple: FruitTuple)
{
let shape:String = fruitTuple.shape
let colour:String = fruitTuple.colour
}
Enum switch via tuple
the edit would work. I'd rename stuff only:
e.g.
case id(Int)
case sentByOwner(String,Bool)
You want to use Query as a factory for predicates I guess!?
Then ... I think you could do this
Extract associated value of enum case into a tuple
You can use pattern matching with if case let
to extract the
associated value of one specific enumeration value:
if case let Barcode.upc(first, second, third, fourth) = productBarcode {
print((first, second, third, fourth)) // (8, 10, 15, 2)
}
or
if case let Barcode.upc(tuple) = productBarcode {
print(tuple) // (8, 10, 15, 2)
}
Sending an enum that is a tuple on a dictionary and back
ConnectionResult
is not a tuple. It is an enum with only one case (which kind of defeats the purpose of an enum), so you need to handle it like an enum.
To get state
and peerID
:
if case .values(let state, let peerID) = result {
// you can access "state" and "peerID" here
} else {
// this will never be reached
}
As you can probably tell, an enum is not suitable here. I recommend changing to an actual tuple:
// create the dict like this
let dict = ["values" : (state:state, peerID:peerID)]
// get state and peerID like this
if let result = dict["values"] as? (state: MCSessionState, peerID: MCPeerID) {
let (state, peerID) = result
} else {
// handle "dict["values"] as? (state: MCSessionState, peerID: MCPeerID)" being nil
}
or a struct
:
struct ConnectionResult {
let state: MCSessionState
let peerID: MCPeerID
}
// create the dict like this
let dict = ["values" : ConnectionResult(state:state, peerID:peerID)]
// get state and peerID like this
if let result = dict["values"] as? ConnectionResult {
let (state, peerID) = (result.state, result.peerID)
} else {
// handle "dict["values"] as? ConnectionResult" being nil
}
You can send the struct/tuple directly too, without putting it in a dictionary first, because the object
parameter accepts Any?
. You just need to cast notification.object
directly to the struct type or tuple type.
Passing var tuple to Enum value
Swift cannot handle passing a var
this way. It can only pass a constant tuple to initialize associated data. This is most likely just an unimplemented feature in the compiler, and I recommend opening a radar (bugreport.apple.com).
The easiest solution is to just declare the tuple as a constant:
let stAnswer = (question: 1, answer: "Student's Answer")
let answerType = AnswerType.Subjective(stAnswer)
If that isn't practical, then make a constant copy before you pass it (which is what the compiler should be able to do automatically).
var stAnswer = (question: 1, answer: "Student's Answer")
let values = stAnswer
let answerType = AnswerType.Subjective(values)
You could also get fancy and use a closure to force a copy. This feels a bit over-tricky to me, but some may prefer it:
let answerType = AnswerType.Subjective({stAnswer}())
You can also use @Rob's solution from the comments (copied here for future readers), which is fine IMO:
let answerType = AnswerType.Subjective(question: stAnswer.question, answer: stAnswer.answer)
How to create an enum function that returns a tuple of Ints?
This works with a few modifications. The key modification is to specify the return type of screenSize()
as (width: Int, height: Int)
so that you can unpack the result.
enum iDeviceType {
case iPhone(String)
case iPad(String)
case other
func screenSize() -> (width: Int, height: Int) {
var myModel = (width: 0, height: 0)
switch self {
case .iPhone(let model):
switch model {
case "XR" : myModel = (width: 400, height: 612)
case "6" : myModel = (width: 465, height: 712)
case "6Plus" : myModel = (width: 465, height: 912)
default: myModel = (width: 365, height: 512)
}
case .iPad(let model):
switch model {
case "Air 1gen" : myModel = (width: 365, height: 512)
case "Air 2gen" : myModel = (width: 405, height: 565)
default: myModel = (width: 365, height: 512)
}
default:
print("not an iOS device")
}
return myModel
}
}
let myModel = iDeviceType.iPhone("XR").screenSize()
print(myModel.height)
612
Making screenSize
a computed property:
Since you're not passing anything to screenSize()
, consider making it a computed property:
change:
func screenSize() -> (width: Int, height: Int) {
to:
var screenSize: (width: Int, height: Int) {
And then access it like this:
let myModel = iDeviceType.iPhone("XR").screenSize
Swift Compiler Error: The enum case has a single tuple as an associated value, but there are several patterns here
Ok, figured it out. Seems like enum
with associated values, where the value type is a tuple, can no longer be matched on a switch
statement like that:
// Works on Xcode 11.3.1, yields error on 11.4 (Swift 5.2)
switch result {
case .error(let err):
//
case .value(let staff, let locations):
//
}
Solution
Values from tuple have to be manually extracted in Xcode 11.4 (Swift 5.2):
// Works on Xcode 11.4
switch result {
case .error(let err):
//
case .value(let tuple):
let (staff, locations) = tuple
//
}
Syntax for expanding a tuple used in an enum when using a switch statement
In addition to your Update: answer:
case .FirstCase(output: let (someString, someInt)):
and
case let .FirstCase(output: (someString, someInt)): // thanks @MartinR
work as well.
By having the output:
label in your enum
case, you have created a named tuple of one value containing a named tuple of two values. If you don't specify output:
in the switch
, Swift is going to attempt to match the outer tuple with the tuple you supply and the count of the items doesn't match.
Providing the output:
label in the pattern allows Swift to know that you are talking about the inner tuple, and it then works.
If you feel output:
is pointless, why include it in your enum definition at all?
Related Topics
How to Create a Struct to Match This JSON
Differencebetween ":" and "=" in Swift
How to Loop Through an Array from the Second Element in Elegant Way Using Swift
Get Lat and Long from Tapped Overlay in Google Maps
How to Create a Multi Line Text Field in Swiftui for MACos
Get Fullpath or Convert to Fullpath
Find Multiple Quoted Words in a String with Regex
Extending View with Extra Function Without Using Anyview
How to Generate a Binding for Each Array Element
Swiftui Present Alert with Input Field
Swift - Get File Path of Currently Opened Document in Another Application
Why Swift Throws Error When Using Optional Param in Closure Func
Arkit -Drop a Shadow of 3D Object on the Plane Surface
Perform Segue from Another Class with Helper Function
How to Cast an Any Value with Nil in It to a Any
How to Load My Own Reality Composer Scene into Realitykit
Difference Between Text("") and Text(Verbatim: "") Initializers in Swiftui