İsteğe Bağlı bir Bool'un değerini kontrol etme


89

İsteğe Bağlı bir Bool'un doğru olup olmadığını kontrol etmek istediğimde, bunu yapmak işe yaramıyor:

var boolean : Bool? = false
if boolean{
}

Bu hatayla sonuçlanır:

İsteğe bağlı tür '@IvalueBool?' boole olarak kullanılamaz; bunun yerine "! = nil" için test edin

Sıfır olup olmadığını kontrol etmek istemiyorum; Döndürülen değerin doğru olup olmadığını kontrol etmek istiyorum.

if boolean == trueİsteğe Bağlı bir Bool ile çalışıyorsam her zaman yapmak zorunda mıyım?

Opsiyonlar BooleanTypeartık uymadığına göre , derleyicinin Bool'un değerini kontrol etmek istediğimi bilmemesi gerekmez mi?


Booleanlar Denkleştirilebilir protokole uyduğundan, isteğe bağlı olanı isteğe bağlı olmayanıyla karşılaştırabilirsiniz. Buraya
Honey

Yanıtlar:


197

İsteğe bağlı boolelerle, kontrolü açık hale getirmek gerekir:

if boolean == true {
    ...
}

Aksi takdirde, isteğe bağlı olarak açabilirsiniz:

if boolean! {
    ...
}

Ancak bu, boole değeri nil- ise, bunu önlemek için bir çalışma zamanı istisnası oluşturur :

if boolean != nil && boolean! {
    ...
}

Beta 5'ten önce mümkündü, ancak sürüm notlarında bildirildiği gibi değiştirildi:

İsteğe bağlı Bool değerleriyle çalışırken karışıklığı önlemek için, isteğe bağlı öğeler artık bir değere sahip olduklarında dolaylı olarak doğru, olmadığında yanlış olarak değerlendirilmez. Bunun yerine, isteğe bağlı bir değerin bir değer içerip içermediğini öğrenmek için == veya! = Operatörleriyle sıfıra karşı açık bir kontrol yapın.

Ek: @MartinR tarafından önerildiği gibi, 3. seçeneğin daha kompakt bir varyasyonu, birleştirme operatörünü kullanıyor:

if boolean ?? false {
    // this code runs only if boolean == true
}

Bu şu anlama gelir: Boole değeri sıfır değilse, ifade boole değerini değerlendirir (ör. sarmalanmamış boole değerini kullanarak), aksi takdirde ifade şu şekilde değerlendirilir: false


4
Üçüncü seçenek, kodun amacını ifade etmenin en iyi yolu olduğu için tercih edilen çözümdür. Kullanmak if letda işe yarar.
Sulthan

29
Kullanarak üçüncü seçenek bir varyantı, "sıfır birleştirme operatörü ??": if boolean ?? false { ... } .
Martin R

4
Ama bunu reddetmek istersem saçma görünmeye başlar: if !(boolean ?? true) { ... }:(
Andreas

2
Son derece kötü bir fikri zorla açmak. Daima kaçınılmalıdır.
Matthieu Riegler

5
İlk seçeneğin nesi var? Bana göre en iyi yol bu.
Vahid Amiri

43

İsteğe bağlı ciltleme

Hızlı 3 ve 4

var booleanValue : Bool? = false
if let booleanValue = booleanValue, booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

Swift 2.2

var booleanValue : Bool? = false
if let booleanValue = booleanValue where booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

Kod let booleanValue = booleanValuedöndürür falseeğer booleanValueolduğunu nilveif blok çalışmaz. Eğer booleanValuedeğil nil, bu kod adlı yeni bir değişken tanımlar booleanValueÇeşidi Bool(yerine, isteğe bağlı bir ait Bool?).

Swift 3 ve 4 kodu booleanValue (ve Swift 2.2 kodu where booleanValue) yeni booleanValue: Booldeğişkeni değerlendirir . ifDoğruysa , blok booleanValue: Bool, kapsamda yeni tanımlanan değişkenle yürütülür (seçeneğin ifblok içinde yeniden sınır değerine başvurmasına izin verir ).

Not: Bağlı sabiti / değişkeni isteğe bağlı sabit / değişkenle aynı şekilde adlandırmak bir Swift kuralıdır. let booleanValue = booleanValue ,. Bu tekniğe değişken gölgeleme denir . Gelenekselden kopabilir ve benzeri bir şey kullanabilirsiniz let unwrappedBooleanValue = booleanValue, unwrappedBooleanValue. Neler olduğunu anlamaya yardımcı olmak için bunu işaret ediyorum. Değişken gölgeleme kullanmanızı öneririm.

 

Diğer Yaklaşımlar

Nil birleşmesi

Nil birleştirme bu özel durum için açıktır

var booleanValue : Bool? = false
if booleanValue ?? false {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

Kontrol etmek falseo kadar net değil

var booleanValue : Bool? = false
if !(booleanValue ?? false) {
    // executes when booleanValue is false
    print("optional booleanValue: '\(booleanValue)'")
}

Not: if !booleanValue ?? falsederlemez.

 

Açmayı isteğe bağlı olarak zorla (kaçının)

Zorla sarmalama, birisinin gelecekte derleyen ancak çalışma zamanında çöken bir değişiklik yapma olasılığını artırır. Bu nedenle, böyle bir şeyden kaçınırım:

var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

 

Genel Bir Yaklaşım

Bu yığın taşma sorusu, özellikle a'nın olup olmadığını nasıl kontrol edeceğinizi sorsa Bool?datrue bir dahilinde ifaçıklamada, bu doğru, yanlış veya diğer ifadelerle Çizelgesi değerini birleştirerek kontrol edip genel bir yaklaşım belirlemek yararlı olur.

İfade karmaşıklaştıkça, isteğe bağlı bağlama yaklaşımını diğer yaklaşımlardan daha esnek ve anlaşılması daha kolay buluyorum. İsteğe bağlı herhangi tip (ki isteğe bağlı bağlayıcı işleri Not Int?, String?vs.).


Boole ifadelerini isteğe bağlı while döngüleri ile kullanmakta güçlük çekiyorum. Sıfır birleştirme operatörü çalışıyor, ancak dağınık ve hataya açık. Kullanmanın bir yolu var mı if let?
jbaraga

@jbaraga, lütfen merak ettiğiniz while döngüsünün bir örneğini gönderin.
Mobile Dan

Bir diziyi yığın olarak kullanırken, bir koşul karşılanana veya yığın boşalana kadar değerleri açmak istiyorum. Örneğin,while array.last < threshold { array.removeLast() }
jbaraga

Bu yığın işlemeyi şununla gerçekleştirebilirsiniz if, let, where: while let last = array.last where last < threshold { array.removeLast() }Swift 2 veya while let last = array.last, last < threshold { array.removeLast() }Swift 3'te
Mobil Dan

Bu daha iyi, teşekkürler. Farkında değildim while let.
jbaraga

2
var enabled: Bool? = true

if let enabled = enabled, enabled == true {
    print("when is defined and true at the same moment")
}

if enabled ?? false {
    print("when is defined and true at the same moment")
}

if enabled == .some(true) {
    print("when is defined and true at the same moment")
}

if enabled == (true) {
    print("when is defined and true at the same moment")
}

if case .some(true) = enabled {
    print("when is defined and true at the same moment")
}

if enabled == .some(false) {
    print("when is defined and false at the same moment")
}

if enabled == (false) {
    print("when is defined and false at the same moment")
}

if enabled == .none {
    print("when is not defined")
}

if enabled == nil {
    print("when is not defined")
}

0

Boolean operatörlerini aşırı yükleyen başka bir çözüm buldum. Örneğin:

public func < <T: Comparable> (left: T?, right: T) -> Bool {
    if let left = left {
        return left < right
    }
    return false
}

Bu, dil değişikliklerinin tamamen "ruhu" içinde olmayabilir, ancak isteğe bağlı ifadelerin güvenli bir şekilde açılmasına izin verir ve while döngüleri de dahil olmak üzere her yerde koşullu ifadeler için kullanılabilir.


1
Özür dilerim, orijinal gönderiye dönüp baktığımda, bu belirli soruyu yanıtlamak yerine daha önceki yorumumda sorduğum soruyu yanıtlıyor.
jbaraga

Bu aşırı yüklemeyi kullanırken çok dikkatli olurum, çünkü nil'in sıfır olmayan bir değerden "büyük" olarak değerlendirilmesini istemediğiniz durumlar olabilir (belirli bağlamlarda tersi sonucu veya muhtemelen alternatif tamamen işleme). Bunun yerine normal sarmalamayı kullanmak, sizi her durumda sıfırları nasıl işlemek istediğinizi açık bir şekilde ele almaya zorlar, böylece beklenmedik sonuçlarla karşılaşma olasılığınız azalır.
John Montgomery

0

Okumayı en kolay bulduğum cevap, bir işlev tanımlamaktır. Çok karmaşık değil ama iş yapıyor.

func isTrue(_ bool: Bool?) -> Bool {
    guard let b = bool else {
        return false
    }
    return b
}

kullanım:

let b: Bool? = true
if isTrue(b) {
    // b exists and is true
} else {
    // b does either not exist or is false
}

0

As Antonio söyledi

İsteğe bağlı Bool değerleriyle çalışırken karışıklığı önlemek için, isteğe bağlı öğeler artık bir değere sahip olduklarında dolaylı olarak doğru, olmadığında yanlış olarak değerlendirilmez. Bunun yerine, isteğe bağlı bir değerin bir değer içerip içermediğini öğrenmek için == veya! = Operatörleriyle sıfıra karşı açık bir kontrol yapın.

Karşılaştığım bir kod satırını anlamaya çalışmak için birkaç saat harcadım, ancak bu konu beni doğru yola soktu.

Bu alıntı Ağustos 2014'e aittir ve o zamandan beri Apple SE-0102 teklifiniNever takiben sundu ve ikincisi onu Eşitlenebilir, Karıştırılabilir, Hata ve Karşılaştırılabilir'e uygun hale getirdi

Artık bir booleanın nilkullanıp kullanmadığını kontrol etmek mümkündür Never?:


var boolean: Bool? = false
boolean is Never? // false
boolean = true
boolean is Never? // false
boolean = nil
boolean is Never? // true

Aslında diğer yaşanmaz türleri kullanabilirsiniz:

public enum NeverEver { }
var boolean: Bool? = false
boolean is NeverEver? // false
boolean = true
boolean is NeverEver? // false
boolean = nil
boolean is NeverEver? // true

Bununla birlikte, artık bir özellik sarmalayıcısı kullanmak da mümkündür :

@propertyWrapper struct OptionalBool {
    public var wrappedValue: Bool?
    public var projectedValue: Bool { wrappedValue ?? false }
    public init(wrappedValue: Bool?) {
        self.wrappedValue = wrappedValue
    }
}

struct Struct {
    @OptionalBool var predicate: Bool?
    var description: String {
        if $predicate {
            return "predicate is true"
        }
        return "predicate is false"
    }
}

var object = Struct()
object.description // "predicate is false"
object.predicate = false
object.description // "predicate is false"
object.predicate = true
object.description // "predicate is true"

ya da:

@propertyWrapper struct OptionalBool {
    var wrappedValue: Bool?
    var projectedValue: OptionalBool { self }
    var isNil: Bool { wrappedValue is Never? }
    var value: Bool { wrappedValue ?? false }
    
    init(wrappedValue: Bool?) {
        self.wrappedValue = wrappedValue
    }
}

struct Struct {
    @OptionalBool var predicate: Bool?
    var description: String {
        if $predicate.value {
            return "predicate is true"
        }
        if !$predicate.isNil {
            return "predicate is false"
        }
        return "predicate is nil"
    }
}

var object = Struct()
object.description // "predicate is nil"
object.predicate = false
object.description // "predicate is false"
object.predicate = true
object.description // "predicate is true"

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.