İsteğe bağlı değişkeni yazdırma


118

Bu kod satırlarıyla deniyorum

class Student {
    var name: String
    var age: Int?

    init(name: String) {
        self.name = name
    }

    func description() -> String {
        return age != nil ? "\(name) is \(age) years old." : "\(name) hides his age."
    }
}

var me = Student(name: "Daniel")
println(me.description())
me.age = 18
println(me.description())

Yukarıdaki kod aşağıdaki gibi üretir

Daniel hides his age.
Daniel is Optional(18) years old.

Sorum şu, neden orada İsteğe Bağlı (18) var, isteğe bağlı olanı ve yalnızca yazdırmayı nasıl kaldırabilirim?

Daniel is 18 years old.

Yanıtlar:


190

Opsiyonel'in gerçekte ne olduğunu anlamalısınız. Swift'e yeni başlayanların çoğu var age: Int?, yaşın bir değeri olan veya olmayan bir Int olduğu anlamına geldiğini düşünür . Ancak bu, yaşın isteğe bağlı olduğu anlamına gelir ve bu, bir Int içerebilir veya içermeyebilir.

description()İşlevinizin içinde Int yazmazsınız, bunun yerine İsteğe Bağlı. Int yazdırmak istiyorsanız, İsteğe Bağlı. Bir İsteğe Bağlı:

if let a = age {
 // a is an Int
}

İsteğe bağlı öğenin bir nesneyi içerdiğinden eminseniz, "zorunlu sarmayı açma" seçeneğini kullanabilirsiniz:

let a = age!

Veya örneğinizde, açıklama işlevinde zaten sıfır için bir testiniz olduğundan, bunu şu şekilde değiştirebilirsiniz:

func description() -> String {
    return age != nil ? "\(name) is \(age!) years old." : "\(name) hides his age."
}

Sanırım bu örneği kullanmak için değiştirirseniz biraz daha iyi olurif let age = age { return ""} else { return "" }
kubi

13
+1 için:Many Swift beginners think var age: Int? means that age is an Int which may or may not have a value. But it means that age is an Optional which may or may not hold an Int.
lee

18

İsteğe bağlı olması, Swift'in değerin türe karşılık gelip gelmediğinden tam olarak emin olmadığı anlamına gelir: örneğin, Int? Swift'in sayının Int olup olmadığından tam olarak emin olmadığı anlamına gelir.

Kaldırmak için kullanabileceğiniz üç yöntem vardır.

1) Türünden kesinlikle eminseniz, açmaya zorlamak için bir ünlem işareti kullanabilirsiniz, örneğin:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

Bir isteğe bağlı olanı açmaya zorlarsanız ve sıfıra eşitse, şu kilitlenme hatasıyla karşılaşabilirsiniz:

görüntü açıklamasını buraya girin

Bu mutlaka güvenli değildir, bu nedenle, türünden ve değerinden emin olmadığınız durumda çökmeyi önleyebilecek bir yöntem aşağıda verilmiştir:

Yöntem 2 ve 3 bu soruna karşı koruma sağlar.

2) Örtülü Olarak Sarılmamış İsteğe Bağlı

 if let unwrappedAge = age {

 // continue in here

 }

Çizelgesi türü artık olduğuna dikkat Int ziyade, Int? .

3) Koruma beyanı

 guard let unwrappedAge = age else { 
   // continue in here
 }

Buradan devam edip sarmalanmamış değişkeni kullanabilirsiniz. Değişkenin türünden eminseniz, yalnızca açmayı zorladığınızdan (bir! İle) emin olun.

Projenizde bol şanslar!


1
dönüş yaşı kullanma! = nil? "(ad) (yaş!) yaşında." : "(ad) yaşını gizler."
leedream

1
Yaşadığım bir sorunla başımı ağrıttı. Yeterince teşekkür edemem.
Bruno Recillas

8

Test / hata ayıklama amaçları için, her zaman nildeğerleri test etmek zorunda kalmadan genellikle isteğe bağlı komutları dizeler olarak çıkarmak istiyorum , bu nedenle özel bir operatör oluşturdum.

Bu cevabı başka bir soruda okuduktan sonra işleri daha da geliştirdim .

fileprivate protocol _Optional {
    func unwrappedString() -> String
}

extension Optional: _Optional {
    fileprivate func unwrappedString() -> String {
        switch self {
        case .some(let wrapped as _Optional): return wrapped.unwrappedString()
        case .some(let wrapped): return String(describing: wrapped)
        case .none: return String(describing: self)
        }
    }
}

postfix operator ~? { }
public postfix func ~? <X> (x: X?) -> String {
    return x.unwrappedString
}

Açıkçası operatör (ve öznitelikleri) beğeninize göre değiştirilebilir veya bunun yerine bir işlev yapabilirsiniz. Her neyse, bu şu şekilde basit kod yazmanıza olanak tanır:

var d: Double? = 12.34
print(d)     // Optional(12.34)
print(d~?)   // 12.34
d = nil
print(d~?)   // nil

Diğer kişinin protokol fikrini entegre etmek, bunu, genellikle isteğe bağlı zincirleme kullanırken ortaya çıkan iç içe isteğe bağlı seçeneklerle bile işe yarayacak hale getirdi. Örneğin:

let i: Int??? = 5
print(i)              // Optional(Optional(Optional(5)))
print("i: \(i~?)")    // i: 5

1
Swift 3'ten itibaren Swift standart kitaplık işlevini de kullanabilirsiniz debugPrint (_: separator: sonlandırıcı :). Ancak bu, dizeyi çift tırnak içinde yazdıracaktır.
psmythirl

@psmythirl: Bilmekte fayda var! Bununla birlikte, bazen isteğe bağlı bir seçeneği Stringbaşka bir yere (örneğin bir günlük / hata mesajı) geçirmek veya yerleştirmek isteyebilirsiniz .
Jeremy

print (d as Any)
DawnSong

7

Güncelleme

Basitçe kullanın me.age ?? "Unknown age!". 3.0.2'de çalışır.

Eski Cevap

Güç açmadan (makine sinyali yok / sıfırsa çökme) bunu yapmanın başka bir güzel yolu da şunlar olabilir:

(result["ip"] ?? "unavailable").description.

result["ip"] ?? "unavailable" İşe de sahip olmalı, ama yok, en azından 2.2'de değil

Elbette "kullanılamıyor" ifadesini size uygun olanla değiştirin: "nil", "bulunamadı" vb.


4

Bunun age!yerine isteğe bağlı kullanımı açmak için age. Şu anda olabilecek isteğe bağlı değeri yazdırıyorsunuz nil. Bu yüzden sarıldı Optional.


4

Swift Optional, nilbazı durumlarda olabilen bir şeydir . % 100 emin bir o ise variableher zaman bazı değere sahip olacak ve geri dönmeyecek nileklenti !buna unwrap zorlamak için değişkenle.

Diğer durumda, değerden çok emin değilseniz, bir if letblok ekleyin veya guarddeğerin var olduğundan emin olmak için aksi takdirde bir çökme ile sonuçlanabilir.

İçin if letbloğun:

if let abc = any_variable {
 // do anything you want with 'abc' variable no need to force unwrap now.
}

For guarddeyimi:

guard koşul yerine getirilmediğinde kontrole dönmek için koşullu bir yapıdır.

Belirli bir değer yoksa döndürmemize izin verdiği için birçok durumda guardover if letblock kullanmayı tercih ederim function. Bir değişkenin var olmasının integral olduğu bir fonksiyon olduğu zaman, onu koruma ifadesinde kontrol edebiliriz ve dönüşü yoktur. örneğin;

guard let abc = any_variable else { return }

Değişken varsa, koruma kapsamı dışında işlevde 'abc' kullanabiliriz.


3

ageisteğe bağlı türdür: Optional<Int>bu nedenle, onu nil ile karşılaştırırsanız, bir değeri varsa veya yoksa, her seferinde yanlış döndürür. Değeri elde etmek için isteğe bağlı olanı açmanız gerekir.

Örneğinizde herhangi bir değer içerip içermediğini bilmiyorsunuz, bu yüzden bunun yerine şunu kullanabilirsiniz:

if let myAge = age {
    // there is a value and it's currently undraped and is stored in a constant
}
else {
   // no value
}

3

Bunu, başka bir görünüm denetleyicisinden dize (özellik) değerini yazdırmak için yaptım.

ViewController.swift

var testString:NSString = "I am iOS Developer"

SecondViewController.swift

var obj:ViewController? = ViewController(nibName: "ViewController", bundle: nil)
print("The Value of String is \(obj!.testString)")

Sonuç:

The Value of String is I am iOS Developer

2
İsteğe bağlı olarak
açılmaya zorlamamalısınız

3

Bildirime göz atın guard:

for student in class {
    guard let age = student.age else { 
        continue 
     }
    // do something with age
}

3

Varsayılan bir değere sahipken:

print("\(name) is \(age ?? 0) years old")

veya isim isteğe bağlı olduğunda:

print("\(name ?? "unknown") is \(age) years old")


1

Tablo görünümü hücrelerimde İsteğe Bağlı ("Dize") alıyordum.

İlk cevap harika. Ve anlamama yardım etti. İşte benim gibi çaylaklara yardım etmek için yaptığım şey.

Özel nesnemde bir dizi oluşturduğum için, her zaman ilk konumda öğelere sahip olacağını biliyorum, böylece onu başka bir değişkene açmaya zorlayabilirim. Sonra bu değişkeni yazdırmak için kullanın veya benim durumumda tablo görünümü hücre metnini ayarlayın.

let description = workout.listOfStrings.first!
cell.textLabel?.text = description

Şimdi çok basit görünüyor, ama anlamam biraz zaman aldı.


-1

Bu, bu sorunun tam cevabı değil, bu tür bir sorunun bir nedeni. Benim durumumda, "if let" ve "guard let" ile bir String'den İsteğe Bağlı'yı kaldıramadım.

Yani kullanmak AnyObject yerine herhangi swift bir dizesi isteğe bağlı kaldırın.

Lütfen cevap için bağlantıya bakın.

https://stackoverflow.com/a/51356716/8334818

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.