Enum of Tuples in Swift

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



Leave a reply



Submit