tipos programacion parametros parametro parameter opcional metodo functions funciones externos swift enumeration

programacion - swift functions parameters



¿Cómo obtener el nombre del valor de enumeración en Swift? (9)

Si tengo una enumeración con valores crudos Integer :

enum City: Int { case Melbourne = 1, Chelyabinsk, Bursa } let city = City.Melbourne

¿Cómo puedo convertir el valor de una city en una cadena Melbourne ? ¿Este tipo de introspección de nombre de tipo está disponible en el idioma?

Algo como (este código no funcionará):

println("Your city is /(city.magicFunction)") > Your city is Melbourne


A partir de Xcode 7 beta 5 ahora puede imprimir nombres de tipos y casos de enum de forma predeterminada utilizando print(_:) , o convertir a String usando el init(_:) String o la sintaxis de interpolación de cadenas. Entonces para tu ejemplo:

enum City: Int { case Melbourne = 1, Chelyabinsk, Bursa } let city = City.Melbourne print(city) // prints "Melbourne" let cityName = "/(city)" // or `let cityName = String(city)` // cityName contains "Melbourne"

Por lo tanto, ya no es necesario definir y mantener una función de conveniencia que active cada caso para devolver un literal de cadena. Además, esto funciona automáticamente para cualquier enumeración, incluso si no se especifica ningún tipo de valor sin formato.

debugPrint(_:) & String(reflecting:) se puede usar para un nombre completamente calificado:

debugPrint(city) // prints "App.City.Melbourne" (or similar, depending on the full scope) let cityDebugName = String(reflecting: city) // cityDebugName contains "App.City.Melbourne"

Tenga en cuenta que puede personalizar lo que se imprime en cada uno de estos escenarios:

extension City: CustomStringConvertible { var description: String { return "City /(rawValue)" } } print(city) // prints "City 1" extension City: CustomDebugStringConvertible { var debugDescription: String { return "City (rawValue: /(rawValue))" } } debugPrint(city) // prints "City (rawValue: 1)"

(No he encontrado una forma de invocar este valor "predeterminado", por ejemplo, para imprimir "La ciudad es Melbourne" sin recurrir a una declaración de cambio. Usar /(self) en la implementación de description / debugDescription causa una recursión infinita)


Los comentarios anteriores String init(_:) & init(reflecting:) String describen exactamente lo que se imprime, dependiendo de a qué se ajuste el tipo reflejado:

extension String { /// Initialize `self` with the textual representation of `instance`. /// /// * If `T` conforms to `Streamable`, the result is obtained by /// calling `instance.writeTo(s)` on an empty string s. /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the /// result is `instance`''s `description` /// * Otherwise, if `T` conforms to `CustomDebugStringConvertible`, /// the result is `instance`''s `debugDescription` /// * Otherwise, an unspecified result is supplied automatically by /// the Swift standard library. /// /// - SeeAlso: `String.init<T>(reflecting: T)` public init<T>(_ instance: T) /// Initialize `self` with a detailed textual representation of /// `subject`, suitable for debugging. /// /// * If `T` conforms to `CustomDebugStringConvertible`, the result /// is `subject`''s `debugDescription`. /// /// * Otherwise, if `T` conforms to `CustomStringConvertible`, the result /// is `subject`''s `description`. /// /// * Otherwise, if `T` conforms to `Streamable`, the result is /// obtained by calling `subject.writeTo(s)` on an empty string s. /// /// * Otherwise, an unspecified result is supplied automatically by /// the Swift standard library. /// /// - SeeAlso: `String.init<T>(T)` public init<T>(reflecting subject: T) }


Consulte las notas de la versión para obtener información sobre este cambio.


Además del soporte de String (...) (CustomStringConvertible) para las enumeraciones en Swift 2.2, también hay un soporte de reflexión algo roto para ellos. Para los casos enum con valores asociados, es posible obtener la etiqueta del caso enum utilizando la reflexión:

enum City { case Melbourne(String) case Chelyabinsk case Bursa var label:String? { let mirror = Mirror(reflecting: self) return mirror.children.first?.label } } print(City.Melbourne("Foobar").label) // prints out "Melbourne"

Al romperse, sin embargo signifiqué que para las enumeraciones "simples", la propiedad calculada de label basada en la reflexión anterior simplemente devuelve nil (boo-hoo).

print(City.Chelyabinsk.label) // prints out nil

La situación con la reflexión debería mejorar después de Swift 3, al parecer. La solución por ahora es String(…) , como se sugiere en una de las otras respuestas:

print(String(City.Chelyabinsk)) // prints out Cheylabinsk


En Swift-3 (probado con XCode 8.1) puede agregar los siguientes métodos en su enumeración:

/** * The name of the enumeration (as written in case). */ var name: String { get { return String(describing: self) } } /** * The full name of the enumeration * (the name of the enum plus dot plus the name as written in case). */ var description: String { get { return String(reflecting: self) } }

Luego puede usarlo como una llamada a método normal en su instancia enum. También podría funcionar en versiones anteriores de Swift, pero no lo he probado.

En tu ejemplo:

enum City: Int { case Melbourne = 1, Chelyabinsk, Bursa var name: String { get { return String(describing: self) } } var description: String { get { return String(reflecting: self) } } } let city = City.Melbourne print(city.name) // prints "Melbourne" print(city.description) // prints "City.Melbourne"

Si desea proporcionar esta funcionalidad a todas sus enumeraciones, puede hacer que sea una extensión:

/** * Extend all enums with a simple method to derive their names. */ extension RawRepresentable where RawValue: Any { /** * The name of the enumeration (as written in case). */ var name: String { get { return String(describing: self) } } /** * The full name of the enumeration * (the name of the enum plus dot plus the name as written in case). */ var description: String { get { return String(reflecting: self) } } }

Esto solo funciona para enums de Swift.


Esto es tan decepcionante

Para el caso en que necesita esos nombres (que el compilador conoce perfectamente la ortografía exacta de, pero se niega a permitir el acceso, ¡gracias Swift team!), Pero no quiere o no puede hacer que String sea la base de su enumeración, una La alternativa detallada y engorrosa es la siguiente:

enum ViewType : Int, Printable { case Title case Buttons case View static let all = [Title, Buttons, View] static let strings = ["Title", "Buttons", "View"] func string() -> String { return ViewType.strings[self.rawValue] } var description:String { get { return string() } } }

Puede usar lo anterior de la siguiente manera:

let elementType = ViewType.Title let column = Column.Collections let row = 0 println("fetching element /(elementType), column: /(column.string()), row: /(row)")

Y obtendrá el resultado esperado (el código de la Columna es similar, pero no se muestra)

fetching element Title, column: Collections, row: 0

En lo anterior, hice que la propiedad de description vuelva a referirse al método de string , pero esta es una cuestión de gusto. También tenga en cuenta que las llamadas variables static deben ser clasificadas por alcance por el nombre de su tipo adjunto, ya que el compilador es demasiado amnésico y no puede recordar el contexto por sí mismo ...

El equipo de Swift debe ser realmente comandado. Crearon una enumeración que no puedes enumerate y en la que puedes usar enumerate son "Secuencias" pero no enumerate .


No hay introspección en los casos enum en este momento. Deberá declararlos de forma manual:

enum City : String, Printable { case Melbourne = "Melbourne" case Chelyabinsk = "Chelyabinsk" case Bursa = "Bursa" var description : String { get { return self.rawValue } } }

Nota : El protocolo Printable actualmente no funciona en áreas de juego. Si quieres ver la cuerda en un patio de recreo, deberás llamar aRaw () manualmente

Si necesita que el tipo sin procesar sea un Int, tendrá que hacer un cambio usted mismo:

enum City : Int, Printable { case Melbourne = 1, Chelyabinsk, Bursa var description : String { get { switch(self) { case Melbourne: return "Melbourne" case Chelyabinsk: return "Chelyabinsk" case Bursa: return "Bursa" } } } }


Para Objective-C enum s la única manera actualmente parece ser, por ejemplo, extender la enumeración con CustomStringConvertible terminando con algo como:

extension UIDeviceBatteryState: CustomStringConvertible { public var description: String { switch self { case Unknown: return "Unknown" case Unplugged: return "Unplugged" case Charging: return "Charging" case Full: return "Full" } } }

Y luego lanzando la enum como String :

String(UIDevice.currentDevice().batteryState)


Para rápido:

extension UIDeviceBatteryState: CustomStringConvertible { public var description: String { switch self { case .unknown: return "unknown" case .unplugged: return "unplugged" case .charging: return "charging" case .full: return "full" } } }

si su variable "batteryState" llame:

self.batteryState.description


Simple pero funciona ...

enum ViewType : Int { case Title case Buttons case View } func printEnumValue(enum: ViewType) { switch enum { case .Title: println("ViewType.Title") case .Buttons: println("ViewType.Buttons") case .View: println("ViewType.View") } }


Swift ahora tiene lo que se conoce como Valor bruto implícitamente asignado . Básicamente, si no le da valores brutos a cada caso y la enumeración es de tipo String, deduce que el valor en bruto del caso es él mismo en formato de cadena. Vamos, dale una oportunidad.

enum City: String { case Melbourne, Chelyabinsk, Bursa } let city = City.Melbourne.rawValue // city is "Melbourne"