moonvader
moonvader

Reputation: 21091

Misunderstanding with enums in Swift

I have enum with cities that looks like

enum Cities: String {
    case la = "Los Angeles"
    case ta = "Tel Aviv"
    case ny  = "New York"
}

And I need to pass sting with city name to one of functions that is waiting for NSString

so this code is not working and I don't understand why

let selectedCity = Cities.ny
myFunc(city : selectedCity)

I get error "Cannot convert value of type 'Cities' to expected argument type 'String!'"

Xcode is suggesting me to use Cities.ny.rawValue as selectedCity.

Upvotes: 0

Views: 1126

Answers (4)

Dominik Bucher
Dominik Bucher

Reputation: 2169

I have better solution, which is much more reasonable... therefore you do this:

enum Cities {

    case la
    case ta
    case ny

  var cityString: String{
    switch self{
    case la:
    return "Los Angeles"
    case ta:
    return "Tel Aviv"
    case ny:
    return "New York"
        }
    }
}

Now you need to call just this:

let selectedCity = Cities.ny.cityString

the reason behind me voting over other ideas is that rawValues should be used for recognizing the case, not for getting the values of them... But that's just my opinion :)

Upvotes: 3

Luca Angeletti
Luca Angeletti

Reputation: 59496

Swift is strongly typed

So when you pass a value to a function argument the compiler checks that it is of the correct type.

Example

Let's declare a function that receive an Int as parameter

func giveMeYourAge(n: Int) {

}

And now let's try to invoke that function passing something that is NOT an Int

giveMeYourAge(n: "Hello World")

Now the compiler gets angry with us ☠️

error: cannot convert value of type 'String' to expected argument type 'Int' giveMeYourAge(n: "Hello World")

And it is right (of course). Infact it is telling us that we cannot pass a String to a function that expects an Intindeed.

Your code

When you declare you enum (let's call it City as properly suggested by @Honey) you create a new type City.

enum City: String {
    case la = "Los Angeles"
    case ta = "Tel Aviv"
    case ny  = "New York"
}

City is something TOTALLY DIFFERENT from a String. And we cannot use City in place of a String or viceversa. (Just like in the previous example Int was totally different from String).

So if you have a function that expects a String as parameter

func myFunc(city : String) {
    // ...
}

of course you won't be able to pass an value of type City to it.

Wait! What about Polymorphism?

Now let's look at this code

class Animal { }
class Dog: Animal { }

func feed(animal: Animal) {

}

let dog = Dog()

feed(animal: dog)

Why does this code compile??? 😨

This is called polymorphism. When we write

 class Dog: Animal { }

we define a new type (Dog) that is more specific than Animal.

Polymorphism does allow us to pass to a function that expects an Animal as param, something that is more specific (like a Dog).

However polymorphism has nothing to do with your example. Even if the syntax is similar.

When you define an enum using this syntax

enum City: String { ... }
  • You are NOT defining a subtype of String.
  • You are NOT creating something more specific than a String.
  • You are NOT using polymorphism.

Instead you are simply creating a new type City that has an instance property (rawValue) of type String.

Upvotes: 4

mfaani
mfaani

Reputation: 36287

It's like you're trying to access a class instance, rather that the property of the instance. It won't work. Specifically what you're trying here is accessing the enum itself which is incorrect. You should access its rawValue property.

From Apple:

You access the raw value of an enumeration case with its rawValue property:

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3

Upvotes: 1

Alex S
Alex S

Reputation: 582

You need to specify raw value to use the string literal, because without that you are just referring to the enum itself.

let selectedCity = Cities.ny.rawValue

Upvotes: 3

Related Questions