1
votes

Sous-énumération rawValue

Considérez le code suivant, où j'ai déclaré un enum avec des sous-énumérations à l'intérieur.

func keyString(for type: LocalizeKey) {
    print(type)
 }
keyString(for: .message(.failure)) // usage

Dans un enum normal sans sous-énumérations, nous pouvons facilement accéder à la propriété .rawValue et obtenir la valeur brute de tout cas que nous avons choisi .

Pour ce cas, j'ai créé une fonction comme celle-ci juste pour vérifier ce que je reçois.

enum LocalizeKey {
case message(Messages)
case buttons(Buttons)
enum Buttons: String {
    case remove = "Remove"
    case add = "Add"
}
enum Messages: String {
    case success = "Success"
    case failure = "Failure"
 }
}

Problème : il n'y a pas d'autres propriétés que .self auxquelles accéder pour ce code LocalizeKey > enum.

Ce que j'essaie de réaliser: peut-être que vous pouvez vous identifier par le nom, j'essaie d'envelopper mes clés localisées, afin que je puisse y accéder facilement en fonction du type de clé, etc. , et la rawValue qui fait référence à la clé réelle ira dans la fonction getLocalizedValue .

Sortie Playground : l'utilisation de la fonction au-dessus de la sortie Playground était

message (__ lldb_expr_21.LocalizeKey.Messages.failure)

Modifier: sans avoir à créer une variable qui s'auto-permute dans tous les cas, imaginez si nous avions +400 clé ce serait probablement un énorme gâchis.


2 commentaires

Si je comprends bien, vous voulez pouvoir accéder aux valeurs de chaîne brutes des Buttons et Messages dans la fonction keyString ?


oui car le LocalizeKey permet de l'appeler l'énumération de base contient les types de clés


3 Réponses :


1
votes

Vous devez basculer sur le paramètre type et effectuer une correspondance de modèle:

extension LocalizeKey {
    var keyString: String {
        switch self {
            case .message(let messages): return messages.rawValue
            case .buttons(let buttons): return buttons.rawValue
        }
    }
}

Vous pouvez également en faire une extension de LocalizeKey :

switch type {
    case .message(let messages): return messages.rawValue
    case .buttons(let buttons): return buttons.rawValue
}


2 commentaires

@MohmmadS wvteijlingen a mentionné un outil de génération de code dans sa réponse, donc je ne pense pas que ce sera un problème d'écrire une telle méthode et qu'il n'y aura pas de fautes de frappe. En ce qui concerne la lisibilité, la plupart des gens comprennent ce que vous faites après avoir lu les premiers cas.


il m'a fallu quelques secondes pour cliquer,: D merci pour la perspicacité, j'étais vraiment proche de cette implémentation mais je voulais voir ce que les autres recommanderaient, j'apprécie votre réponse, mon pote.



1
votes

Vous allez devoir changer quelque part. S'il n'y a qu'une poignée de "sous-énumérations", il est probablement le plus simple d'écrire un commutateur manuellement:

func keyString(for type: LocalizeKey) {
  switch type {
  case .message(let message):
    print(message.rawValue)
  case .buttons(let button):
    print(button.rawValue)
  }
}

Si vous ne voulez pas écrire cela manuellement, vous avez soit pour modifier votre structure de données afin qu'elle ne soit pas nécessaire, ou utilisez un outil de génération de code qui génère le passe-partout pour vous.


1 commentaires

Il est donc impératif de changer, mais en ce qui concerne le problème technique de l'énumération, pourriez-vous suggérer une approche différente ou plus efficace pour réaliser ce que j'essaie de faire?



1
votes

Bien que les réponses mentionnées fournissent la solution, je mentionnerais le problème de l'approche elle-même:

À ce stade, chaque nouveau cas (clé) doit être ajouté dans votre commutateur déclaration avec une valeur associée, qui semble être un codage standard indésirable; Je suppose que vous pouvez imaginer à quoi cela ressemblera lorsque vous aurez beaucoup de cas dans les énumérations.

Par conséquent, je recommanderais de suivre une approche pour être plus dynamique au lieu d'ajouter la valeur de chaque cas manuellement dans une instruction switch . Exemple:

keyString(for: LocalizeKey.Buttons.add) // Add
keyString(for: LocalizeKey.Messages.success) // Success

Nous appliquons la même logique pour votre code, avec quelques améliorations pour le rendre plus facile à maintenir.

Sur cette base, vous capable d'implémenter votre fonction comme:

func keyString(for type: Localizable) {
    print(type)
}

Utilisation:

protocol Localizable {
    var value: String { get }
}

extension RawRepresentable where Self: Localizable, Self.RawValue == String {
    var value: String { return rawValue }
}

extension CustomStringConvertible where Self: RawRepresentable, Self.RawValue == String {
    var description: String { return rawValue }
}

struct LocalizeKey {

    enum Buttons: String, Localizable, CustomStringConvertible {
        case remove = "Remove"
        case add = "Add"
    }

    enum Messages: String, Localizable, CustomStringConvertible {
        case success = "Success"
        case failure = "Failure"
    }
}

IMO, je trouve que l'appeler de cette façon semble être plus lisible, plus simple que l'approche proposée ( keyString (for: .message (.failure)) ).


0 commentaires