2016-05-25 3 views
1

Encore en train de s'habituer à l'utilisation de OptionSetType dans Swift.plus de test rapide idiomatique pour l'ensemble d'options?

En bon vieux C, si j'avais quelque chose comme

typedef enum { 
    CHAR_PROP_BROADCAST   =0x01, 
    CHAR_PROP_READ    =0x02, 
    CHAR_PROP_WRITE_WITHOUT_RESP =0x04, 
    CHAR_PROP_WRITE    =0x08, 
    CHAR_PROP_NOTIFY    =0x10, 
    CHAR_PROP_INDICATE   =0x20, 
    CHAR_PROP_SIGNED_WRITE  =0x40, 
    CHAR_PROP_EXT    =0x80 
} CharacteristicProperty; 

je pouvais tester un ensemble de drapeaux avec quelque chose de simple comme:

if ((propertiesMask & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) != 0) ... 

L'alternative Swift pourrait ressembler

let properties:CBCharacteristicProperties = [.Write, .Read, .Indicate] 
!properties.intersect([.Indicate, .Notify]).isEmpty 

Existe-t-il une façon plus idiomatique de faire ce test? Pas un fan de la! à l'avant. Mais sinon, semble assez simple, sauf que je suis vraiment intéressé quand il y a une intersection. Cela m'a amené à vouloir ajouter le mien.

extension OptionSetType { 
    func hasIntersection(other:Self) -> Bool { 
     return !self.intersect(other).isEmpty 
    } 
} 

Ce qui me permet alors d'écrire

properties.hasIntersection([.Indicate, .Notify]) 

est-il un moyen de mieux/plus idiomatiques de le faire? Ai-je roulé le mien et ai-je manqué quelque chose?

+0

Pour éviter le '!', Vous pouvez faire 'prope rties.intersect ([. Indiquer, .Notifier]). count> 0' – sschale

Répondre

1

Il y a cette méthode du protocole SetAlgebraType qui met en œuvre OptionSetType:

isDisjointWith(_: Self) -> Bool

Renvoie true ssi self.intersect (autre) .isEmpty.

Ainsi, vous pouvez réduire votre test:

!properties.isDisjointWith([.Indicate, .Notify]) 

ou

properties.isDisjointWith([.Indicate, .Notify]) == false 

Vous pouvez également comparer les valeurs brutes avec les opérateurs binaires, comme vous le feriez dans C:

(properties.rawValue & (CharacteristicProperties.Notify.rawValue | CharacteristicProperties.Indicate.rawValue)) != 0 

Exemple de code complet (dans un terrain de jeu):

struct CBCharacteristicProperties : OptionSetType { 
    let rawValue: UInt 
    init(rawValue: UInt) { self.rawValue = rawValue } 

    static let Broadcast   = CBCharacteristicProperties(rawValue:0x01) 
    static let Read    = CBCharacteristicProperties(rawValue:0x02) 
    static let WriteWithoutResp = CBCharacteristicProperties(rawValue:0x04) 
    static let Write    = CBCharacteristicProperties(rawValue:0x08) 
    static let Notify    = CBCharacteristicProperties(rawValue:0x10) 
    static let Indicate   = CBCharacteristicProperties(rawValue:0x20) 
    static let SignedWrite  = CBCharacteristicProperties(rawValue:0x40) 
    static let Ext    = CBCharacteristicProperties(rawValue:0x80) 
} 

let properties = CBCharacteristicProperties([.Write, .Read, .Indicate]) 
print(!properties.intersect([.Indicate, .Notify]).isEmpty) 
print(!properties.isDisjointWith([.Indicate, .Notify])) 
print(properties.isDisjointWith([.Indicate, .Notify]) == false) 
print((properties.rawValue & (CBCharacteristicProperties.Notify.rawValue | CBCharacteristicProperties.Indicate.rawValue)) != 0) 

Résultat:

"true" 
"true" 
"true" 
"true" 
0

La solution réelle que je trouve la plus attrayante à la fin a été d'ajouter simplement l'extension suivante:

extension SetAlgebraType { 
    var notEmpty:Bool { 
     return self.isEmpty.NOT 
    } 
} 

Cela m'a permis d'écrire du code:

if properties.intersect([.Indicate, .Notify]).notEmpty { 
    ... 
} 
+0

Où obtenez-vous le membre 'NOT'? C'est sur une valeur 'Bool' et, à ma connaissance, aucun membre n'existe. – ColGraff

+0

Une autre de mes propres extensions. Désolé :( –

+0

Je me doutais que ce pourrait être.Pas besoin d'être désolé, j'étais juste curieux. – ColGraff