140 votes

Comment créer des énumérations bitmask de type NS_OPTIONS en Swift ?

Dans la documentation d'Apple sur l'interaction avec les API en C, ils décrivent la manière suivante NS_ENUM -Les énumérations de style C marquées sont importées comme des énumérations Swift. C'est logique, et puisque les énumérations en Swift sont facilement fournies par la fonction enum il est facile de voir comment créer notre propre type de valeur.

Plus bas, il est dit ceci à propos de NS_OPTIONS -Options de style C marquées :

Swift importe également les options marquées du symbole NS_OPTIONS macro. Alors que options se comportent de manière similaire aux énumérations importées, les options peuvent aussi supporter certaines opérations binaires, telles que & , | y ~ . En Objective-C, on représente un ensemble d'options vide par la constante zéro ( 0 ). Dans Swift, utilisez nil pour représenter l'absence de toute option.

Étant donné qu'il n'y a pas de options en Swift, comment créer une variable d'options de type C pour travailler avec ?

3 votes

Le très célèbre "NSHipster" de @Mattt contient une description détaillée de l'appareil. RawOptionsSetType : nshipster.com/rawoptionsettype

0 votes

1voto

Afin d'éviter un codage dur des positions des bits, ce qui est inévitable lorsque l'on utilise (1 << 0) , (1 << 1) , (1 << 15) etc. ou pire encore 1 , 2 , 16384 etc. ou une variante hexadécimale, on pourrait d'abord définir les bits dans un fichier enum puis laisser ledit enum faire le calcul du bit ordinal :

// Bits
enum Options : UInt {
    case firstOption
    case secondOption
    case thirdOption
}

// Byte
struct MyOptions : OptionSet {
    let rawValue: UInt

    static let firstOption  = MyOptions(rawValue: 1 << Options.firstOption.rawValue)
    static let secondOption = MyOptions(rawValue: 1 << Options.secondOption.rawValue)
    static let thirdOption  = MyOptions(rawValue: 1 << Options.thirdOption.rawValue)
}

1voto

Peter Ahlberg Points 936

J'utilise ce qui suit : j'ai besoin des deux valeurs que je peux obtenir, rawValue pour indexer les tableaux et value pour les drapeaux.

enum MyEnum: Int {
    case one
    case two
    case four
    case eight

    var value: UInt8 {
        return UInt8(1 << self.rawValue)
    }
}

let flags: UInt8 = MyEnum.one.value ^ MyEnum.eight.value

(flags & MyEnum.eight.value) > 0 // true
(flags & MyEnum.four.value) > 0  // false
(flags & MyEnum.two.value) > 0   // false
(flags & MyEnum.one.value) > 0   // true

MyEnum.eight.rawValue // 3
MyEnum.four.rawValue  // 2

Et si l'on a besoin de plus, il suffit d'ajouter une propriété calculée.

enum MyEnum: Int {
    case one
    case two
    case four
    case eight

    var value: UInt8 {
        return UInt8(1 << self.rawValue)
    }

    var string: String {
        switch self {
        case .one:
            return "one"
        case .two:
            return "two"
        case .four:
            return "four"
        case .eight:
            return "eight"
        }
    }
}

1voto

slashlos Points 310

Re : Création de bacs à sable et de signets à l'aide de jeux d'options avec plusieurs options

let options:NSURL.BookmarkCreationOptions = [.withSecurityScope,.securityScopeAllowOnlyReadAccess]
let temp = try link.bookmarkData(options: options, includingResourceValuesForKeys: nil, relativeTo: nil)

solution pour ne pas avoir à combiner les options pour les créations, utile lorsque toutes les options ne sont pas mutuellement exclusives.

0voto

Ethan Points 962

Réponse de Nate c'est bien mais je ferais du bricolage, comme ça :

struct MyOptions : OptionSetType {
    let rawValue: Int

    static let None         = Element(rawValue: 0)
    static let FirstOption  = Element(rawValue: 1 << 0)
    static let SecondOption = Element(rawValue: 1 << 1)
    static let ThirdOption  = Element(rawValue: 1 << 2)
}

0voto

geek1706 Points 844

Utiliser un type de jeu d'options, dans le swift 3 utiliser OptionSet

struct ShippingOptions: OptionSet {
    let rawValue: Int

    static let nextDay    = ShippingOptions(rawValue: 1 << 0)
    static let secondDay  = ShippingOptions(rawValue: 1 << 1)
    static let priority   = ShippingOptions(rawValue: 1 << 2)
    static let standard   = ShippingOptions(rawValue: 1 << 3)

    static let express: ShippingOptions = [.nextDay, .secondDay]
    static let all: ShippingOptions = [.express, .priority, .standard]
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X