2016-07-31 17 views
1

Ich möchte in der Lage sein, die Werte eines NSUnderlineStyle in Swift korrekt zu lesen. Es ist komplizierter als es scheint.Überprüfen des Wertes eines NSUnderlineStyle BitMask

Zuerst eine kurze Überprüfung. NSUnderlineStyle ist eine Aufzählung mit den folgenden Werten:

NSUnderlineStyleNone = 0x00, 
NSUnderlineStyleSingle = 0x01, 
NSUnderlineStyleThick = 0x02, 
NSUnderlineStyleDouble = 0x09, 
NSUnderlinePatternSolid = 0x0000, 

NSUnderlinePatternDot = 0x0100, 
NSUnderlinePatternDash = 0x0200, 
NSUnderlinePatternDashDot = 0x0300, 
NSUnderlinePatternDashDotDot = 0x0400, 

NSUnderlineByWord = 0x8000 

Es gibt drei verschiedene Gruppen von Optionen. Entsprechend Apple's documentation, die "Stil, Muster und optional by-Word-Maske sind OR'd zusammen, um den Wert für NSUnderlineStyleAttributeName und NSStrikethroughStyleAttributeName zu produzieren."

NSUnderlineStyle nicht implementieren die neue OptionSet Protocol, was bedeutet, dass Werte mit ganzzahligen bitweisen Operationen (offensichtlich) kombiniert werden müssen. Wenn dies der Fall wäre, wäre etwas Ähnliches wie folgt möglich:

let operation: NSDragOperation = [.copy, .move] 
if operation.contains(.copy) { 
    // Yay! 
} 

Aber leider funktioniert das nicht.

Mein Verständnis ist, dass korrekt mit Zahlen Bitflags zu überprüfen, ist es (A & B == B), wenn B in A. ist

jedoch, dies scheint nicht für NSUnderlineStyle zu arbeiten, und Ich bin mir nicht sicher warum. Ich bin kein Bitmaskenexperte.

Hier ist ein Beispielcode, der das Problem demonstriert.

style single found 
pattern dash dot dot found 
by word flag found 

Aber produziert statt:

let style = NSUnderlineStyle.styleSingle.rawValue | 
    NSUnderlineStyle.patternDashDotDot.rawValue | 
    NSUnderlineStyle.byWord.rawValue 

if style & NSUnderlineStyle.styleSingle.rawValue == NSUnderlineStyle.styleSingle.rawValue { 
    NSLog("style single found") 
} 

if style & NSUnderlineStyle.styleDouble.rawValue == NSUnderlineStyle.styleDouble.rawValue { 
    NSLog("style double found") 
} 

if style & NSUnderlineStyle.styleThick.rawValue == NSUnderlineStyle.styleThick.rawValue { 
    NSLog("style thick found") 
} 

if style & NSUnderlineStyle.patternSolid.rawValue == NSUnderlineStyle.patternSolid.rawValue { 
    NSLog("pattern solid found") 
} 

if style & NSUnderlineStyle.patternDash.rawValue == NSUnderlineStyle.patternDash.rawValue { 
    NSLog("pattern dash found") 
} 

if style & NSUnderlineStyle.patternDot.rawValue == NSUnderlineStyle.patternDot.rawValue { 
    NSLog("pattern dot found") 
} 

if style & NSUnderlineStyle.patternDashDot.rawValue == NSUnderlineStyle.patternDashDot.rawValue { 
    NSLog("pattern dash dot found") 
} 

if style & NSUnderlineStyle.patternDashDotDot.rawValue == NSUnderlineStyle.patternDashDotDot.rawValue { 
    NSLog("pattern dash dot dot found") 
} 

if style & NSUnderlineStyle.byWord.rawValue == NSUnderlineStyle.byWord.rawValue { 
    NSLog("by word flag found") 
} 

sollten Dieser Code produzieren

style single found 
pattern solid found 
pattern dash dot dot found 
by word flag found 

Es gibt andere Fälle, in denen dies nicht gelingt.

Was kann ich tun, um Stile richtig zu lesen?

Jede Hilfe würde sehr geschätzt werden. Auch wenn jemand einen Einblick hat, warum dies scheitert, wäre das auch großartig.

Antwort

2

Die Aufzählungswerte für "Stil" und "Muster" sind keine Bit-Flags. Zum Beispiel haben NSUnderlineStyleNone und NSUnderlinePatternSolid beide den Wert Null, und NSUnderlineStyleSingle und NSUnderlineStyleDouble haben ein Bit (0x01) gemeinsam.

Sie müssen die Bits extrahieren, um jede Gruppe entsprechenden (Art, Muster, flags) und diesen Wert gegen die möglichen Enumerationswerten vergleichen, getrennt für jede Gruppe.

Leider bietet Apple keine Bitmasken für jede Gruppe (so weit , wie ich sehen kann), so dass wir unsere eigenen definieren. Die Style-Werte (0x00, 0x01, 0x02, 0x09) verwenden alle die Bits 0 ... 3, und die Pattern-Werte (0x0, 0x100, 0x200, 0x300, 0x400) verwenden alle Bits 8 ... 11.Das legt nahe, die folgenden Definitionen:

let underlineStyleMask = 0x000F 
let underlinePatternMask = 0x0F00 

, die dann als

verwendet werden können
// Check style: 
switch style & underlineStyleMask { 
case NSUnderlineStyle.styleNone.rawValue: 
    NSLog("no style") 
case NSUnderlineStyle.styleSingle.rawValue: 
    NSLog("single style") 
case NSUnderlineStyle.styleDouble.rawValue: 
    NSLog("double style") 
case NSUnderlineStyle.styleThick.rawValue: 
    NSLog("thick style") 
default: 
    NSLog("unknown style") 
} 

// Check pattern: 
switch style & underlinePatternMask { 
case NSUnderlineStyle.patternSolid.rawValue: 
    NSLog("solid pattern") 
case NSUnderlineStyle.patternDot.rawValue: 
    NSLog("dot pattern") 
case NSUnderlineStyle.patternDash.rawValue: 
    NSLog("dash pattern") 
case NSUnderlineStyle.patternDashDot.rawValue: 
    NSLog("dash dot pattern") 
case NSUnderlineStyle.patternDashDotDot.rawValue: 
    NSLog("dash dot dot pattern") 
default: 
    NSLog("unknown pattern") 
} 

// Check flags: 
if style & NSUnderlineStyle.byWord.rawValue != 0 { 
    NSLog("by word flag") 
} 

Aber beachten Sie, dass diese brechen könnte, wenn Apple mehr Definitionen in die Zukunft fügt hinzu, zum Beispiel

NSUnderlineStyleStrange = 0x22 

würde fälschlicherweise als NSUnderlineStyleThick erkannt werden.

+0

Hallo Martin, danke fürs Erklären mit einem Beispiel! Das funktioniert wunderbar. Kannst du vielleicht erklären, wie du es wusstest, um es mit 0x0F00 und 0x000F zu maskieren? Ich hoffe, dass ich dieses Niveau irgendwann erreichen kann und ich würde gerne Ihren Denkprozess kennenlernen. –

+1

@JosephE .: Siehe aktualisierte Antwort. –