Swift: Anahtar durumunda isteğe bağlı değere karşı test etme


94

Swift'de, isteğe bağlı bir içeriğin içeriğine göre değiştirilen değeri test eden bir anahtar deyiminde, isteğe bağlı varsa , durumu atlayarak nasıl bir durum yazabilirim nil?

İşte bunun nasıl görünebileceğini hayal ediyorum:

let someValue = 5
let someOptional: Int? = nil

switch someValue {
case someOptional:
    // someOptional is non-nil, and someValue equals the unwrapped contents of someOptional
default:
    // either, someOptional is nil, or someOptional is non-nil but someValue does not equal the unwrapped contents of someOptional
}

Tam olarak böyle yazarsam, derleyici paketlenmemiş olduğundan şikayet eder someOptional, ancak !sonuna ekleyerek açıkça açarsam , elbette her zaman someOptionaliçerdiği bir çalışma zamanı hatası alırım nil. ?Bunun yerine eklemek !bana biraz mantıklı gelebilir (sanırım isteğe bağlı zincirleme ruhu içinde), ancak derleyici hatasını ortadan kaldırmaz (yani isteğe bağlı olanı açmaz).

Yanıtlar:


113

İsteğe bağlı, enumşunun gibidir:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case none
    case some(T)

    // ...
}

Böylece, bunları her zamanki "İlişkili Değerler" eşleme modelleriyle eşleştirebilirsiniz:

let someValue = 5
let someOptional: Int? = nil

switch someOptional {
case .some(someValue):
    println("the value is \(someValue)")
case .some(let val):
    println("the value is \(val)")
default:
    println("nil")
}

Eşleştirme istiyorsanız someValue, koruma ifadesini kullanarak :

switch someValue {
case let val where val == someOptional:
    println(someValue)
default:
    break
}

Swift> 2.0 için

switch someValue {
case let val where val == someOptional:
    print("matched")
default:
    print("didn't match; default")        
}

5
Swift 3'te bazılarının / hiçbirinin küçük harf olduğuna dikkat edin, yani .some yerine .some kullanırsınız
Adam

55

Xcode 7'den itibaren, " x?eşanlamlı olarak opsiyonellere karşı model eşleştirmek için yeni bir model kullanılabilir .some(x)". Bu, Swift 2 ve sonrasında rintaro'nun cevabının aşağıdaki varyasyonunun da işe yarayacağı anlamına gelir :

let knownValue = 5

switch someOptional {
case knownValue?:
    // Contents of someOptional are knownValue, defined above.
case let otherValue?:
    // Contents of someOptional are *any* non-nil value not already tested for.
    // Unwrapped contents are assigned to otherValue for use inside this case.
default:
    // someOptional is nil.
}

3
Soru, isteğe bağlı olmayan bir değeri isteğe bağlı bir değerle eşleştirmekle ilgilidir, bu yanıt tam tersidir.
Martin R

2
Doğru, ancak bu cevap başlangıçta OP tarafından soruya bir güncelleme olarak yazılmıştı, bu yüzden onun için reddedilemez bir şekilde uygulanabilir bir çözümdü; Bunu bir topluluk wiki yanıtına taşıdım. Belki @GeorgeWS, anahtar ve durum değiştirgelerini değiştirmenin neden kullanım durumu için işe yaradığını açıklayabilir?
Slipp D. Thompson

2
Ben biraz kayboldum. ilk iki vakanız arasındaki fark nedir? someValue?diğer bazı tanımlanan değerdir, ancak case let val?sadece güvenli Çizelgesi versiyonudur someOptional?!
Honey

@Honey Bu gerçek dünyaya ait bir kod örneği değildir; bu sadece rintaro'nun cevabının bir varyasyonu. Öyleyse gidip ona şu soruyu sorun - cevabım işlevsel olarak onun koduyla eşdeğerdir. Yine de rintaro'ya soracak olsaydın, cevabın 1 olacağına inanıyorum. Bu, bağlantılı Apple belgelerinde ne olduğunu yansıtıyor; 2. yalnızca sözdizimini gösterir; belirgin bir hesaplama veya iş mantığı hedefi gerçekleştirmez.
Slipp D. Thompson

@Honey Ayrıca, rintaro'nun cevabı orijinal olarak Swift 1.x için yazılmış ve Swift 2 için güncellendi. Artık sürümün derlenmemesi mümkündür let. Şu anda bunun neden gün içinde işe yaradığını hatırlayamıyorum.
Slipp D. Thompson

10

In Swift 4 kullanabilirsiniz ExpressibleByNilLiteral: İsteğe isteğe wrappe için Apple

https://developer.apple.com/documentation/swift/optional

Misal

enum MyEnum {
    case normal
    case cool
}

biraz

let myOptional: MyEnum? = MyEnum.normal

switch smyOptional {
    case .some(.normal): 
    // Found .normal enum
    break

    case .none: 
    break

    default:
    break
}

Yok

let myOptional: MyEnum? = nil

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    // Found nil
    break

    default:
    break
}

varsayılan

let myOptional: MyEnum? = MyEnum.cool

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    break

    default:
    // Found .Cool enum
    break
}

Değer içeren numaralandırma

enum MyEnum {
    case normal(myValue: String)
    case cool
}

biraz değer

let myOptional: MyEnum? = MyEnum.normal("BlaBla")

switch smyOptional {
case .some(.normal(let myValue)) where myValue == "BlaBla":
    // Here because where find in my myValue "BlaBla"
    break

// Example for get value
case .some(.normal(let myValue)):
    break

// Example for just know if is normal case enum
case .some(.normal):
    break

case .none:
    break

default:

    break
}

Bahsediyorsunuz ExpressibleByNilLiteralama o zaman bu aslında enum bildirimlerinde kullanılmıyor vs. Bu nedir?
pkamb
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.