"Dize enterpolasyonu, isteğe bağlı bir değer için bir hata ayıklama açıklaması üretir; bunu açık hale getirmek mi istedin? " Xcode 8.3 beta'da?


89

Beta 8.3'ten beri, zilyonlarca uyarı "Dize enterpolasyonu, isteğe bağlı bir değer için bir hata ayıklama açıklaması üretir; bunu açık hale getirmek mi istediniz?" kodumda göründü.

Örneğin, seçeneklerin sıfıra yol açabileceği aşağıdaki durumda uyarı ortaya çıktı:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"

Daha önce tasarlandığı gibi, benim (ve derleyicinin) opsiyonellerin 'sıfır' olarak enterpolasyonlu olması sorun değildi. Ancak derleyici fikrini değiştirdi.

Derleyicinin önerdiği şey, aşağıdaki gibi açıklamaya sahip bir String yapıcısı eklemektir:

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"

Açıkçası, sonuçlar açık ama bence çok külfetli. Daha iyi bir seçenek var mı? Tüm bu uyarıları düzeltmek zorunda mıyım yoksa bir sonraki betayı beklemek daha mı iyi?

Açıklama için ekran görüntüsü


28
Ne gerçekten sinir bozucu bir uyarı ...
Jonny

Swift 3kendiminkini kırdım logve printbunun yerine sadece kullanarak bir hata yaptım . Her zaman kendi paketleyicinizi yaratmalısınız, aksi takdirde bu tür "yeni özellik" ile mahvolursunuz.
superarts.org

Yanıtlar:


107

Bu, elde edilen dizeye enterpolasyon yapılmasının genellikle istenmeyen olması nedeniyle bu çekme talebinde yapılan bir değişikliktir Optional(...)ve örtük olarak sarmalanmamış seçeneklerin olduğu durumlarda özellikle şaşırtıcı olabilir . Bu değişikliğin tam tartışmasını burada posta listesinde görebilirsiniz .

Çekme isteği tartışmasında belirtildiği gibi (ne yazık ki Xcode tarafından olmasa da) - uyarıyı susturmanın kullanımından biraz daha hoş bir yolu, String(describing:)enterpolasyon yaptığınız şeyin isteğe bağlı türüne bir atama eklemektir, örneğin:

var i: Int? = 5
var d: Double? = nil

print("description of i: \(i as Int?)")    // description of i: Optional(5)
print("description of d: \(d as Double?)") // description of d: nil

Bu da şu şekilde genelleştirilebilir as Optional:

print("description of i: \(i as Optional)") // description of i: Optional(5)
print("description of d: \(d as Optional)") // description of d: nil

Swift 5'te, SE-0228 tarafından sunulan yeni dizi enterpolasyon sistemiyle , başka bir seçenek de şunlar için özel bir appendInterpolationaşırı yük eklemektir DefaultStringInterpolation:

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

var i: Int? = 5
var d: Double? = nil

print("description of i: \(optional: i)") // description of i: Optional(5)
print("description of d: \(optional: d)") // description of d: nil

Ve isterseniz, uyarıyı tamamen bir modül içinde (veya olarak işaretlerseniz belirli bir dosya içinde) devre dışı bırakmak için bağımsız değişken etiketini bile kaldırabilirsiniz fileprivate:

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

var i: Int? = 5
var d: Double? = nil

print("description of i: \(i)") // description of i: Optional(5)
print("description of d: \(d)") // description of d: nil

Şahsen ben argüman etiketini tutmayı tercih ederim.


Tekliften bu değişikliğin kalıcı olup olmayacağı belli değil mi? Ne düşünüyorsun? @Hamish
Stéphane de Luca

@ StéphanedeLuca E-posta listesinde ?? "nil", biraz popüler gibi görünen uyarının susturulmasına izin vermek gibi diğer çözümlerle ilgili oldukça fazla tartışma vardı , bu nedenle yakın gelecekte başka bir teklifte görünebilir. Bu geçici çözümün idealden daha az olduğu konusunda hemfikirim - kişisel olarak, Optional(...)güçlü bir isteğe bağlı olarak dizeye eklenmeyi beklemenin oldukça açık olduğunu hissediyorum - bu IMO uyarısına ihtiyaç duyan yalnızca IUO'lar oldu. Ancak Swift sürekli olarak gelişiyor, bu nedenle bunların tümü daha sonra değişebilir. Ama şimdilik elimizde olan bu.
Hamish

Ayrıca biraz 'ilgili' bir sorunla karşılaştım, eğer artık burada kutudan çıkarmazsanız stackoverflow.com/questions/42543512/… bir göz atabilirseniz? @Hamish
Stéphane de Luca

... her durumda bu kod crazyness geçerli:guard result == nil else { print("result was \(result as Optional)") return }
loretoparisi

1
@loretoparisi Neden kullanmıyorsunuz if let? yani if let result = result { print("result was \(result)"); return }. Tüm erken dönüşlerin gardiyanlar ile yapılması gerekmez.
Hamish

28

Bu sorunu çözmenin iki kolay yolu.

Seçenek 1:

Birincisi , bir patlama (!) Kullanarak döndürmek istediğiniz değeri "sarmaya zorlayarak" olacaktır .

var someValue: Int? = 5
print(someValue!)

Çıktı:

5

Seçenek 2:

Diğer yol, daha iyi bir yol olabilir - döndürmek istediğiniz değeri "güvenli bir şekilde açmaktır" .

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

Çıktı:

5

Seçenek 2 ile gitmenizi tavsiye ederim.

İpucu: Her zaman sarmalanacak değere sahip olup olamayacağımızdan emin olmadığımız için, mümkün olduğunda zorla sarmadan (!) Kaçının.



Bunu ciddiye almak istiyorsanız, sarmayı zorla açmak NO-GO'dur. Demek istediğim, sadece bir şeyi yazdırmak istediğiniz için uygulamayı çökertme riskine giriyorsunuz? Bu çok kötü bir öneri. Seçenek 2 tamam, sanırım 2ht "İpucu" yeterli değil, cevabı değiştirin!
Martin Mlostek

16

String kullanmak gibi görünüyor (tanımlayan: isteğe bağlı) en basitidir.

varsayılan değer ?? Dize olmayanlar için bir anlam ifade etmez, örneğin Int.
Int nil ise, o zaman günlüğün başka bir Int için varsayılan değil 'nil' göstermesini istersiniz, örn.

Test edilecek bazı oyun alanı kodları:

var optionalString : String? = nil
var optionalInt : Int? = nil

var description_ = ""
description_ = description_ + "optionalString: \(String(describing: optionalString))\r"
description_ = description_ + "   optionalInt: \(String(describing: optionalInt))\r"

print(description_)

Çıktı

optionalString: nil
optionalInt: nil

13

Xcode 8.3'e güncelleme yaptıktan ve bir çok uyarı mesajı aldıktan sonra, orijinal çıktı davranışına daha çok benzeyen, eklenmesi kolay, hem kodda hem de çıktıda "String (açıklama :)" kullanımının ayrıntılarını azaltan aşağıdakileri buldum .

Temel olarak, isteğe bağlı öğedeki şeyi açıklayan bir Dize veren İsteğe Bağlı bir uzantı ekleyin veya ayarlanmamışsa basitçe "sıfır". Ek olarak, isteğe bağlı öğedeki şey bir Dize ise, tırnak içine alın.

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}

Ve oyun alanında kullanım:

var s : String?
var i : Int?
var d : Double?

var mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = nil    i = nil   d = nil"

d = 3
i = 5
s = ""
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = ""    i = 5   d = 3.0"

s = "Test"
d = nil
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = "Test"    i = 5   d = nil"

Aşağıdaki bağlantıdan yardım için teşekkürler:

kontrol-if-değişken-bir-isteğe bağlı ve ne-türü-sarar


Bu çözüm isteğe bağlı zincirde çalışmıyor. Beğen a?.b?.c.orNil.
Vincent Sit

11

Ole Begeman'ın bunun için yaptığı düzeltmeye bakın . Onu seviyorum. Daha ???sonra şu şekilde kullanabileceğiniz bir operatör oluşturur :

var someValue: Int? = 5
print("The value is \(someValue ??? "unknown")")
// → "The value is 5"
someValue = nil
print("The value is \(someValue ??? "unknown")")
// → "The value is unknown"

5
Bunu açıklayan blog gönderisine bir referans faydalı olabilir diye düşünüyorum: oleb.net/blog/2016/12/optionals-string-interpolation
Nicolai Henriksen

8

Bu uyarıyı içeren satırda görüntülenen sarı üçgene çift tıklayın. Bu FixIt'i iki çözümle gösterecektir .

Ekran görüntüsü eklendi

  1. String(describing:)Bu uyarıyı susturmak için kullanın :

    Bunu kullanarak String(describing:<Variable>)

    Örneğin. :String(describing: employeeName)

  2. default valueBu uyarıyı önlemek için bir sağlayın :

    Bunu kullanarak (<Variable> ?? default value)

    Örneğin.: employeeName ?? “Anonymous” as! String


1
Evet, Nil-Coalescing Operatörüne de gidecektim: developer.apple.com/library/content/documentation/Swift/…
kevinius

1
Mükemmel cevap! Sağlayacağınız alternatif bir dizgi değeriniz varsa, Nil-coalescing bununla iyi çalışır
Lance Samaria

2

Swift 5

Benim çözümüm, extensionhangi açılacak Optionalnesneyi yapmak Any.

Nesneyi günlüğe kaydettiğinizde veya yazdırdığınızda, gerçek objectveya <nil>⭕️(metin ve görsel karakter kombinasyonu) görebilirsiniz. Özellikle konsol günlüğüne bakmak yararlıdır.

extension Optional {
    var logable: Any {
        switch self {
        case .none:
            return "<nil>|⭕️"
        case let .some(value):
            return value
        }
    }
}

// sample
var x: Int?
print("Logging optional without warning: \(x.logable)")
// → Logging optional without warning: <nil>|⭕️

0

Adsız bir parametre ile isteğe bağlı bir genel Tür kabul eden bir enterpolasyon yöntemi oluşturun. Tüm sinir bozucu uyarılarınız sihirli bir şekilde kaybolacak.

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}
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.