Swift IF LET nasıl değerlendirilir?


90

Bu kodu Swift sitesinde ve çeşitli gönderilerde gördüm ve temelleri kavramaya çalışıyorum. Bu hat nasıl değerlendirilir?

if let name = optionalName {

Ad == isteğe bağlı ad olmadığı için kafam karıştı, değeri atıyor, öyleyse bu nasıl doğru oluyor ve john appleeed ile değiştirdiğinizde nil ile değiştirdiğinizde hala eşit olacağına göre neden doğru değil?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
Swift belgelerinde "isteğe bağlı ciltleme"
Martin R

3
Dev.iachieved.it/iachievedit/?p=314 adresindeki isteğe bağlı öğelere ayrıntılı bir şekilde bakıldığında , if letsözdizimi isteğe bağlı bağlama olarak bilinir.
Joe

Yanıtlar:


105

Esasen satır, "yeni değişkenin nameisteğe bağlı olmayan sürümüne eşit olmasına izin verebiliyorsanız optionalName, onunla aşağıdakileri yapın" diyor. Martin'in işaret ettiği gibi, buna İsteğe Bağlı Bağlama denir .

Bunun tek amacı, isteğe bağlı bir değişkenin gerçek bir değer içerip içermediğini test etmek ve isteğe bağlı olmayan formu geçici bir değişkene bağlamaktır. Bu, isteğe bağlı bir "sarmayı açmanın" veya başka bir deyişle isteğe bağlı içinde bulunan değere erişmenin güvenli yoludur. Hiçbir şekilde eşitliği test etmez. Yalnızca isteğe bağlı bir değer içinde bir değerin varlığını test ediyor.


2
Aşağıya indiğimde bunu okuyacağım, hızlı girişin tam başlangıcındayım ve bunu açıklamıyor. açıklama çok mantıklı, teşekkürler.
DeadZero

1
Opsiyonel değişkenin - if optionalName! = Nil {selamlama = "Merhaba, (isim)"}
Nuibb

4
@Nuibb çünkü kullanırken if letdeğeri isteğe bağlı olmayan bir değişkene bağlarız ( namebu örnekte). Örneğiniz derlenmez çünkü artık çağrılan bir değişken yok name. Örneğinizi kullanmak optionalNameiçin değiştirirseniz, olarak yazdırılır Hello, Optional("John Appleseed"). Sıfıra karşı kontrol ettikten sonra zorla sarmalamayı kullanabilirsiniz Hello, \(optionalName!), ancak kodun bu bölümünü kontrol etmeden bir yere taşırsanız, bu daha fazla hataya meyillidir.
2016

30

Bir isteğe bağlı ya ayarlanmış ya da ayarlanmamıştır (sıfır ya da sıfır değil) ... bizi önemli bir kararla bırakıyor. "Kodumuzu her iki durumda da 2 durum için doğru çalışacak şekilde nasıl yazmalıyız?". İsteğe bağlı olanı açma şeklimiz, bizim için buna karar verir.

İsteğe bağlı olarak ayarlanmayan bir seçeneğe karşı koymak için kullanabileceğiniz birkaç yaklaşım vardır.

  • Crash!
  • Değeri bir şeye varsayılan olarak ayarlayın - ayarlanmamışsa.
  • Gracefully yani hiçbir şey başarısız değil, aynı zamanda eğer değerin ayarlandığı, daha sonra atayın.
  • İncelikle yani ancak hiçbir şey başarısız olursa (tek atama sadece daha var) bir şeyler yapmak ... değer ayarlandı.

Aşağıda 4 yaklaşım bulunmaktadır


Kullanılması zorunlu unwrapping kilitlenmesine eğer bir değeri yoktur. Bu değere sahip olmak hayati önem taşıyorsa, örneğin bir filmin başlığı (her filmin bir adı OLMALIDIR) bunu yapmak isteyebilirsiniz . !zorla sarmalamak için kullanılır.

movieTitle = movie.title!

Sıfır birleştirme kullanmak size daha fazla kontrol sağlayacak başka bir yoldur , yani değer ayarlanmadıysa çökmez veya ayarlanmazsa 'hiçbir şey ayarlamaz' ... Söylediğinizi yapardı. yapmak için, örneğin bir ad ayarlanmamışsa filmin adını varsayılan olarak / untitled_movie olarak ayarlar. ??sıfır birleştirme için kullanılır.

var movieTitle = movie.title ?? "untitled_Movie"

Kullanımı isteğe bağlı zincirleme hiçbir şey yapmayacak eğer bir değeri olmayan ve değeri olacaktır eğer bir değeri vardır. Bunu, değer setine sahip olmanın hayati önemi olmayan bir şey için yaparsınız, örneğin oyuncunuzun temsilcisinin adı için . ?isteğe bağlı zincirleme için kullanılır.

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

Kullanmak if-let(veya guardiki farklı isteğe bağlı bağlama türü ) size daha fazla kontrol sağlar , değer ayarlanmadıysa çökmez. Değer ayarlanmışsa, bir şeyler yapabilirsiniz. Ayarlanmamışsa, bir elseifade ekleyebilirsiniz .

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

Zorla sarmayı açmanın bir şekilde önerilmemesi nedeniyle, sarmayı açmanın en yaygın kullanılan yolu budur. Neden cesaretinin kırıldığı hakkında daha fazla tartışma için buraya bakın . Arasında iyi bir karşılaştırma için guardve if-letbkz.guard vs. if-let


Kenar notu:

İsteğe bağlı bağlama ve isteğe bağlı zincirleme genellikle birlikte kullanılır:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

MovieTitle'ın asla bir dizeden başka bir şey olamayacağı ve tüm dizelerin movieTitle için geçerli olduğu bir durumda zorla sarmalamadan neden vazgeçilsin? (ve "başlıksız film" istiyorum "" istemiyorum) Bu durum için tek doğru yol paketinden çıkarmaktır, yanlış bilgi olduğu için "zorla açmanın biraz cesareti kırılır" yazan kısmı kaldırabilirseniz harika olur .
Andy

Bir ağ araması yaptığınızı ve sunucu ekibinin bazı geliştiricilerinin kötü bir karar verdiğini ve film başlığını göndermeyi unuttuğunu varsayalım. Uygulamanızın üretimde kilitlenmesini istiyor musunuz? Veya sadece bilinmeyen bir başlık mı yazıyorsunuz? Nitekim IMDb'deki bazı filmlerin başlığı yoktur :). Buna ek olarak, zorla sarmalamada herhangi bir günlüğe kaydetme veya onaylama yapmadığınız anlamına gelir. Bu kötü. Çünkü asıl nedenin ne olduğunu bilemeyeceksiniz.
Honey

Bu çok basit bir argümandır, "her zaman zorla açmayı kullan" demedim. Örneğinizde zorunlu sarmalamayı kullanmamanız, her örnekte sarmalamaya zorlamadan vazgeçildiği anlamına gelmez. Size sunduğunuz dört çözüm arasından zorla paketten çıkarmanın tek doğru çözüm olduğu bir senaryo verdim. Önceki yorumumda belirtilen senaryoya daha iyi bir çözüm sağlayabilir misiniz? Değilse, lütfen bağlamı dikkate alınmadan cesareti kırılmadığı için, "zorunlu sarmadan çıkarmaya biraz cesaret edemiyor" hakkındaki yorumunuzu değiştirmeyi düşünün.
Andy

Bir şeyi "" olarak varsayılan yapıyorsanız, artık isteğe bağlı değildir
Honey

Örneğin, bu "" değeri film şeridinde oluşturulan bir UILabel örneğinin metin özelliğinden geliyor, isteğe bağlıdır çünkü dinamik olarak oluşturursanız sıfır olabilir, ancak burada onu dinamik olarak oluşturmuyorsunuz, bu nedenle her zaman bir dize değeri içerir . Bu durumda zorunlu sarılmayı kullanmayacak mısınız, bunun yerine if-let ile sarmayı açıp varsayılan değeri "" ile aynı olan bir değer mi sunacaksınız? Yapabilirsin, ama bu anlamsız, gereksiz ve çok sözlü. Ya bir hata olsa bile her zaman bir sözlük döndürecek bir HTTP kitaplığı kullanıyorsanız? Bağlama bağlıdır.
Andy

4

İf sözdizimi 2 farklı koşulu kabul eder. İkincisi, isteğe bağlı bir bağlama, bir mantıksal değildir. Yazabileceğiniz gibi bu kafa karıştırıcı:

if let name = optionalName {

Ama değil

if (let name = optionalName) {

Apple belgeleri (Swift referansı):

Değeri koşulu tipte olmalıdır Boolya da bir tipi köprülü Bool. Koşul, İsteğe Bağlı Bağlamada tartışıldığı gibi isteğe bağlı bir bağlayıcı bildirim de olabilir .


3

if yalnızca boole ifadelerini alır, bunun dışında bir hata verir, bu nedenle bu kod parçası

if let name = optionalName {

}else{

}

isteğe bağlıAdı nil ise, koşul yanlıştır ve else deyimi yürütülür. Bununla birlikte, isteğe bağlıAdı bir değere sahipse, isteğe bağlı değer sarmalanmaz / sabit değişkene, yani ad'a atanır.


1

Zayıf referanslarla çalışırken , isteğe bağlı türleri kullanmak daha iyi olacaktır eğer kodunuzu korumak ve çökmeleri önlemek için izin verin İşte örnekler

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
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.