Swift'de isteğe bağlı değer nedir?


267

Gönderen Apple'ın belgelerinde :

Eksik olan değerlerle çalışmak için ifve letbirlikte kullanabilirsiniz . Bu değerler isteğe bağlı olarak gösterilir. İsteğe bağlı bir değer bir değer içerir veya nildeğerin eksik olduğunu göstermek için içerir . ?Değeri isteğe bağlı olarak işaretlemek için bir değer türünden sonra bir soru işareti ( ) yazın.

Neden isteğe bağlı bir değer kullanmak istersiniz?



1
İsteğe bağlı, Seçenek / Belki monadının bir uygulaması olarak da görülebilir . Buradaki blog , aksi takdirde zor bir kavramın ne olduğunu açıklamak için iyi bir iş çıkarıyor.
StuartLC

tldr: “Swift, bir değerin ne zaman eksik olabileceği ve varlığının ne zaman garanti edileceği konusunda net olmanızı istiyor.” king'in mükemmel cevabının altından
jonatan

Yanıtlar:


531

Swift'te isteğe bağlı bir değer ya da değeri olmayan bir türdür. Opsiyoneller, ?herhangi bir türe a eklenerek yazılır :

var name: String? = "Bertie"

Seçenekler (Generics ile birlikte) anlaşılması en zor Swift kavramlarından biridir. Nasıl yazıldıklarından ve kullanıldıklarından dolayı, ne oldukları hakkında yanlış bir fikir edinmek kolaydır. Yukarıdaki isteğe bağlı olanı normal bir String oluşturmakla karşılaştırın:

var name: String = "Bertie" // No "?" after String

Sözdiziminden, isteğe bağlı bir Dize, sıradan bir Dize'ye çok benziyor gibi görünüyor. Değil. İsteğe bağlı bir Dize, bazı "isteğe bağlı" ayarların açık olduğu bir Dize değildir. Özel bir String türü değildir. Bir Dize ve isteğe bağlı bir Dize tamamen farklı türlerdir.

İşte bilinmesi gereken en önemli şey: İsteğe bağlı bir tür kaptır. İsteğe bağlı bir Dize, bir Dize içerebilecek bir kaptır. İsteğe bağlı Int, Int içeren bir kaptır. İsteğe bağlı bir tür parsel düşünün. Açmadan önce (veya seçeneklerin dilinde "paketini aç"), bir şey içerip içermediğini bilemezsiniz.

Herhangi bir Swift dosyasına "İsteğe Bağlı" yazıp ⌘ üzerine tıklayarak seçeneklerin Swift Standart Kitaplığında nasıl uygulandığını görebilirsiniz . İşte tanımın önemli kısmı:

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

İsteğe bağlı, enumiki durumdan biri olabilen yalnızca bir tanesidir: .noneveya .some. Eğer öyleyse .some, yukarıdaki örnekte String"Merhaba" olacak ilişkili bir değer vardır . Bir isteğe bağlı, ilişkili değere bir tür vermek için Generics kullanır. İsteğe bağlı bir Dize türü değil String, Optionaldaha doğrusu Optional<String>.

Swift'in opsiyonellerle yaptığı her şey, okuma ve yazma kodunu daha akıcı hale getirmek için sihirdir. Ne yazık ki bu aslında çalışma şeklini gizliyor. Daha sonra bazı hilelerden geçeceğim.

Not: İsteğe bağlı değişkenler hakkında çok konuşacağım, ancak isteğe bağlı sabitler oluşturmak da iyidir. Oluşturulan tür türlerini daha kolay anlamak için tüm değişkenleri türleriyle işaretliyorum, ancak kendi kodunuzda olmak zorunda değilsiniz.


Optionals nasıl oluşturulur

İsteğe bağlı oluşturmak için, ?sarmak istediğiniz türden sonra a ekleyin . Herhangi bir tür isteğe bağlı olabilir, hatta kendi özel türleriniz bile. Tür ile ?. Arasında boşluk olamaz .

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

Opsiyonelleri kullanma

nilBir değeri olup olmadığını görmek için isteğe bağlı olanı karşılaştırabilirsiniz :

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

Bu biraz kafa karıştırıcı. Bu isteğe bağlı bir şey ya da başka bir şey anlamına gelir. Nil ya da "Bob". Bu doğru değil, isteğe bağlı başka bir şeye dönüşmez. Bunu nil ile karşılaştırmak, okunması kolay kod yapmak için bir numaradır. İsteğe bağlı nil değerine eşitse, bu yalnızca sıralamanın şu anda ayarlı olduğu anlamına gelir .none.


Yalnızca isteğe bağlı seçenekler boş olabilir

İsteğe bağlı olmayan bir değişkeni nil olarak ayarlamaya çalışırsanız bir hata alırsınız.

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

Opsiyonellere bakmanın bir başka yolu, normal Swift değişkenlerini tamamlayıcıdır. Bunlar, bir değere sahip olacağı garanti edilen bir değişkenin karşılığıdır. Swift, belirsizlikten nefret eden dikkatli bir dildir. Değişkenlerin çoğu isteğe bağlı olmayan olarak tanımlanır, ancak bazen bu mümkün değildir. Örneğin, bir görüntüyü önbellekten veya ağdan yükleyen bir görünüm denetleyicisi düşünün. Görüntü denetleyicisinin oluşturulduğu sırada bu görüntüye sahip olabilir veya olmayabilir. Görüntü değişkeni değerini garanti etmenin bir yolu yoktur. Bu durumda, isteğe bağlı yapmanız gerekir. nilGörüntü alındığında başlar ve isteğe bağlı olarak bir değer elde edilir.

İsteğe bağlı bir program kullanılması programcıların amacını ortaya çıkarır. Herhangi bir nesnenin sıfır olabileceği Objective-C ile karşılaştırıldığında, Swift bir değerin ne zaman eksik olabileceği ve varlığının ne zaman garanti edileceği konusunda net olmanızı gerektirir.


İsteğe bağlı kullanmak için, "paketini açar"

İsteğe bağlı Stringbir gerçek yerine kullanılamaz String. Sarılmış değeri isteğe bağlı olarak kullanmak için, değerinin paketini açmanız gerekir. Bir isteğe bağlı paketini açmanın en basit yolu !, isteğe bağlı adın sonuna bir etiket eklemektir . Buna "kuvvet açma" denir. İsteğe bağlı (orijinal tür olarak) içindeki değeri döndürür, ancak isteğe bağlı ise nilbir çalışma zamanı çökmesine neden olur. Paketini açmadan önce bir değer olduğundan emin olmalısınız.

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

İsteğe bağlı kontrol ve kullanma

Paketini açmadan ve isteğe bağlı kullanmadan önce nil'i her zaman kontrol etmeniz gerektiğinden, bu yaygın bir kalıptır:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

Bu modelde bir değerin var olup olmadığını kontrol edersiniz, o zaman emin olduğunuzda, onu açmak için geçici bir sabit haline getirmeye zorlarsınız. Bu çok yaygın bir şey olduğu için Swift, "izin ver" i kullanarak bir kısayol sunuyor. Buna "isteğe bağlı bağlama" denir.

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

Bu geçici bir sabit (veya değişken değiştirmek eğer yaratır letile varolan kapsamı yalnızca en parantez içindedir). "UnwrappedMealPreference" veya "realMealPreference" gibi bir ad kullanmak zorunda kalmak bir yük olduğundan, Swift, orijinal değişken adını yeniden kullanmanıza izin verir ve parantez kapsamı içinde geçici bir ad oluşturur

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

Farklı bir değişkenin kullanıldığını gösteren bazı kodlar şunlardır:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

İsteğe bağlı ciltleme, isteğe bağlı olarak nil olup olmadığını kontrol ederek çalışır. Değilse, isteğe bağlı olanı sağlanan sabitin içine açar ve bloğu yürütür. Xcode 8.3 ve sonraki sürümlerde (Swift 3.1), böyle bir isteğe bağlı yazdırmaya çalışmak işe yaramaz bir uyarıya neden olacaktır. Susturmak için isteğe bağlı debugDescriptionolanları kullanın :

print("\(mealPreference.debugDescription)")

Seçenekler nelerdir?

Opsiyonellerin iki kullanım durumu vardır:

  1. Başarısız olabilecek şeyler (bir şey bekliyordum ama hiçbir şeyim yoktu)
  2. Şimdi hiçbir şey olmayan ama daha sonra bir şey olabilir (ve tersi)

Bazı somut örnekler:

  • Orada orada olur muyum olmaz gibi olabilir Bir özellik middleNameveya spousebir bölgesi Personsınıfta
  • Bir dizide eşleşme aramak gibi bir değer veya hiçbir şey döndüremeyen bir yöntem
  • Bir dosyanın içeriğini (normalde dosyanın verilerini döndürür) okumaya çalışmak gibi bir sonuç döndüren veya hata alıp hiçbir şey döndürmeyen bir yöntemdir, ancak dosya mevcut değildir
  • Her zaman ayarlanması gerekmeyen ve genellikle başlatma işleminden sonra ayarlanan temsilci özellikleri
  • İçin weaksınıflarında özellikleri. İşaret ettikleri şey nilher zaman ayarlanabilir
  • Belleği geri kazanmak için serbest bırakılması gerekebilecek büyük bir kaynak
  • Ayrı bir veri kullanmak yerine bir değerin ne zaman ayarlandığını (henüz yüklenmemiş veriler> veriler) bilmenin bir yoluna ihtiyacınız olduğunda Boolean

Objective-C'de seçenekler mevcut değildir, ancak sıfır döndüren eşdeğer bir kavram vardır. Bir nesneyi döndürebilen yöntemler bunun yerine nil döndürebilir. Bu, "geçerli bir nesnenin yokluğu" anlamına gelir ve genellikle bir şeylerin yanlış gittiğini söylemek için kullanılır. Yalnızca Objective-C nesneleriyle çalışır, ilkellerle veya temel C türleriyle (numaralandırmalar, yapılar) çalışmaz. Amaç-Cı genellikle bu değerlerin olmadığını temsil çeşitlerini uzman vardı ( NSNotFoundgerçekten NSIntegerMax, kCLLocationCoordinate2DInvalidbir koordinat değeri geçersiz temsil etmek, -1ya da negatif değeri de kullanılır). Kodlayıcının bu özel değerleri bilmesi gerekir, böylece her vaka için belgelenmeli ve öğrenilmelidir. Bir yöntem alınamıyorsanil parametre olarak , bunun belgelenmesi gerekir. Objective-C'de,niltıpkı tüm nesnelerin işaretçi olarak tanımlandığı, ancak nilbelirli (sıfır) bir adrese işaret ettiği gibi bir göstericiydi . Swift'te, nilbelirli bir türün olmaması anlamına gelen bir değişmezdir.


İle karşılaştırıldığında nil

Eskiden herhangi bir isteğe bağlı olarak aşağıdakileri kullanabilirsiniz Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

Swift'in daha yeni sürümlerinde kullanmanız gerekir leatherTrim != nil. Bu neden? Sorun şu ki, a Booleanisteğe bağlı olarak sarılabilir. Eğer böyle bir şey varsa Boolean:

var ambiguous: Boolean? = false

iki tür "yanlış" vardır, biri değerin olmadığı, diğeri değerin olduğu ancak değerin olduğu false. Swift belirsizlikten nefret eder, bu yüzden şimdi her zaman isteğe bağlı olarak kontrol etmelisiniz nil.

Bir isteğe bağlı amacının ne olduğunu merak edebilirsiniz Boolean? Diğer seçeneklerde olduğu gibi, .nonedurum değerin henüz bilinmediğini gösterebilir. Bir şebeke çağrısının diğer ucunda anket yapmak biraz zaman alabilir. Opsiyonel Boolelara " Üç Değerli Boolelar " da denir


Hızlı hileler

Swift, seçeneklerin çalışmasına izin vermek için bazı hileler kullanır. Sıradan görünümlü isteğe bağlı kodun bu üç satırını düşünün;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

Bu satırların hiçbiri derlenmemelidir.

  • İlk satır, iki farklı tür olan bir String dizesi kullanarak isteğe bağlı bir String ayarlar. Bu bir Stringtür bile olsa farklı
  • İkinci satır isteğe bağlı bir String'i nil, iki farklı tip olarak ayarlar
  • Üçüncü satır, isteğe bağlı bir dizeyi nil, iki farklı türle karşılaştırır

Bu satırların çalışmasına izin veren seçeneklerin bazı uygulama ayrıntılarını inceleyeceğim.


İsteğe bağlı oluşturma

?Swift derleyici tarafından etkinleştirilen, sözdizimsel bir şeker oluşturmak için kullanmak . Bunu uzun bir yoldan yapmak istiyorsanız, böyle bir isteğe bağlı oluşturabilirsiniz:

var name: Optional<String> = Optional("Bob")

Bu , isteğe bağlı olan ilişkili türü parantez içinde kullanılan türden ihlal eden Optionalilk başlatıcısıdır public init(_ some: Wrapped).

İsteğe bağlı bir oluşturma ve ayarlama işleminin daha da uzun yolu:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

İçin isteğe bağlı nil

Başlangıç ​​değeri olmayan bir isteğe bağlı oluşturabilir veya başlangıç ​​değeri olan bir tane oluşturabilirsiniz nil(her ikisinin de aynı sonucu vardır).

var name: String?
var name: String? = nil

Seçeneklerin eşit olmasına izin vermek nilprotokol tarafından etkinleştirilir ExpressibleByNilLiteral(önceden adlandırılmıştı NilLiteralConvertible). İsteğe bağlı, Optional'ın ikinci başlatıcısı ile oluşturulur public init(nilLiteral: ()). Dokümanlar ExpressibleByNilLiteral, seçenekleriniz dışında hiçbir şey için kullanmamanız gerektiğini söylüyor , çünkü bu, kodunuzdaki nil'in anlamını değiştirecek, ancak bunu yapmak mümkün:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

Aynı protokol önceden oluşturulmuş bir isteğe bağlı olarak ayarlamanızı sağlar nil. Tavsiye edilmemesine rağmen, nil hazır bilgi başlatıcısını doğrudan kullanabilirsiniz:

var name: Optional<String> = Optional(nilLiteral: ())

İsteğe bağlı ile karşılaştırılması nil

İsteğe bağlı olarak, Optionaltanımda görebileceğiniz iki özel "==" ve "! =" Operatörü tanımlanır. Birincisi ==, isteğe bağlı olanların nil'e eşit olup olmadığını kontrol etmenizi sağlar. İlişkili türler aynıysa, .none olarak ayarlanan iki farklı seçenek her zaman eşit olacaktır. Nil ile karşılaştırdığınızda, sahne arkasında Swift aynı .none olarak ayarlanmış aynı türden bir isteğe bağlı oluşturur, daha sonra bunu karşılaştırma için kullanır.

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

İkinci ==operatör iki seçeneği karşılaştırmanıza izin verir. Her ikisinin de aynı tür olması ve bu türün uyumlu olması gerekir Equatable(normal "==" operatörüyle işleri karşılaştırmaya izin veren protokol). Swift (muhtemelen) iki değeri açar ve doğrudan karşılaştırır. Ayrıca seçeneklerden birinin veya her ikisinin olduğu durumu da ele alır .none. nilDeğişmez değerle karşılaştırma arasındaki farkı not edin .

Ayrıca, herhangi bir Equatabletürü bu tür isteğe bağlı bir ambalajla karşılaştırmanıza olanak tanır :

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

Sahne arkasında, Swift isteğe bağlı olmayan isteğe bağlı olarak karşılaştırma önce sarar. Değişmez değerlerle de çalışır ( if 23 == numberFromString {)

İki ==operatör olduğunu söyledim , ama aslında nilkarşılaştırmanın sol tarafına koymanıza izin veren bir üçüncü

if nil == name { ... }

Adlandırma Seçenekleri

İsteğe bağlı türleri isteğe bağlı olmayan türlerden farklı olarak adlandırmak için Swift kuralı yoktur. Kullanıcılar, adın isteğe bağlı olduğunu ("isteğe bağlıMiddleName" veya "possibleNumberAsString" gibi) göstermek için bir şey eklemekten kaçınır ve bildirimin isteğe bağlı bir tür olduğunu göstermesine izin verir. İsteğe bağlı bir değeri tutmak için bir şey adlandırmak istediğinizde bu zorlaşır. "MiddleName" adı, bunun bir String türü olduğunu ima eder; bu nedenle, String değerini bundan aldığınızda, genellikle "actualMiddleName" veya "unwrappedMiddleName" veya "realMiddleName" gibi adlarla karşılaşabilirsiniz. İsteğe bağlı ciltleme kullanın ve bu sorunu aşmak için değişken adını yeniden kullanın.


Resmi tanım

itibaren Swift Programlama Dili "Temel" :

Swift ayrıca bir değerin yokluğunu işleyen isteğe bağlı türleri de sunar. Opsiyoneller ya “bir değer vardır ve x'e eşittir” ya da “hiç bir değer yoktur” der. Opsiyoneller, Objective-C'de işaretçilerle nil kullanmaya benzer, ancak sadece sınıflar için değil, her tür için çalışırlar. Opsiyoneller Objective-C'deki sıfır işaretçilerden daha güvenli ve daha etkileyici ve Swift'in en güçlü özelliklerinin çoğunun kalbinde yer alıyor.

Opsiyoneller, Swift'in güvenli bir dil olduğu gerçeğine bir örnektir. Swift, kodunuzun çalışabileceği değer türleri hakkında net olmanıza yardımcı olur. Kodunuzun bir kısmı bir Dize bekliyorsa, security yazdığınızda kodu yanlışlıkla Int olarak iletmeniz engellenir. Bu, geliştirme sürecinde hataları mümkün olduğunca erken yakalamanızı ve düzeltmenizi sağlar.


Bitirmek için, 1899'dan opsiyonellerle ilgili bir şiir:

Dün merdivende
orada olmayan bir adamla tanıştım
Bugün tekrar orada değildi
Keşke, keşke

Antigonca


Daha fazla kaynak:


5
@KaanDedeoglu Ne yazık ki Steve çok fazla isteğe bağlı. O buradaydı ve şimdi değil.
nevan king

19
if myStringartık derlemiyor. Gerek if myString != nil. Belgelere bakın .
Pang

5
için en iyi ve en açık açıklama? ve ! Web'de bulduğum Swift'te kullanıyorum. teşekkür ederim
mindbomb

2
mateo , Derinlik ve kolay örneklere ulaşarak Opsiyonelleri derinlemesine açıklar.
iluvatar_GR

4
Bu açıklama için teşekkürler, Apple'ın kendi belgelerinden çok daha açık.
yesthisisjoe

16

Bir örneğini ele alalım NSError, döndürülecek bir hata yoksa Nil'i döndürmeyi isteğe bağlı yapmak istersiniz. Hata yoksa buna değer atamanın bir anlamı yoktur.

var error: NSError? = nil

Bu ayrıca varsayılan bir değere sahip olmanızı sağlar. İşlev bir şey iletilmezse, yöntemi varsayılan bir değer olarak ayarlayabilirsiniz

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

"Eğer sıfır ise, herhangi bir ifadenin sonucu da sıfırdır" cümlesi yanlıştır. ifadede isteğe bağlı bir değer olsa bile func isNil<T>(t: T?) -> Bool { return t == nil }geri döner . truenil
dönüş

İnanılmaz derecede kötü kod örneği. Daha iyi bir şey düşünemez misin? Neden basit değil return x == 5? 5 hakkında bu kadar özel olan ne?
Atomosk

Hayır, 2 yıl önce daha iyi bir şey düşünemedim. Bugün evet, ama bu noktaya değiniyor mu? Evet. @Atomosk girişi için teşekkürler, gerçekten yararlı.
John Riselvato

12

nilSwift'te işaret eden bir değişkeniniz olamaz - işaretçiler ve boş işaretçiler yoktur. Ancak bir API'da, genellikle belirli bir değer türünü veya değer eksikliğini belirtmek istersiniz - örneğin, penceremin bir temsilcisi var ve eğer öyleyse, kim? Opsiyonel olanlar, Swift'in bunu yapmanın tip güvenli, bellek güvenli yoludur.


11

Acemi olarak kafamdaki belirsizliği temizlemek için yukarıdakilerin çoğunu özetleyen kısa bir cevap verdim:

Objective-C'nin aksine, hiçbir değişken Swift'te nil içeremez , bu nedenle İsteğe bağlı değişken türü eklendi (değişkenler "?" İle eklenir):

    var aString = nil //error

En büyük fark, İsteğe bağlı değişkenlerin değerleri doğrudan depolamamasıdır (normal bir Obj-C değişkeni gibi) iki durum içerir : " bir değeri vardır " veya " nil " vardır:

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

Bu, farklı durumlarda bu değişkenleri kontrol edebilirsiniz:

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

"!" sonek, bunlara sarılmış değerlere de erişebilirsiniz, ancak bunlar varsa . (yani sıfır değildir ):

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

Bu yüzden "?" ve "!" ve varsayılan olarak hepsini kullanmayın. (bu benim en büyük şaşkınlığımdı)

Yukarıdaki yanıta da katılıyorum: İsteğe bağlı tür bir boole olarak kullanılamaz .


7

Değeri olmayan objektif C değişkenleri 'nil' değerine eşitti (0 ve false ile aynı 'nil' değerlerini kullanmak da mümkündür), bu nedenle koşullu ifadelerde değişkenler kullanmak mümkündür (Değerleri olan değişkenler 'TRUE ile aynıdır) 've değeri olmayanlar' FALSE 'değerine eşitti).

Swift, 'isteğe bağlı değer' sağlayarak tip güvenliği sağlar. Yani oluşan hataların farklı tipte değişkenler atamasını önler.

Yani Swift'te, koşullu ifadelerde yalnızca boolelar sağlanabilir.

var hw = "Hello World"

Burada, 'hw' bir dize olsa bile, C nesnesindeki gibi bir if ifadesinde kullanılamaz.

//This is an error

if hw

 {..}

Bunun için,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

5

İsteğe bağlı değer, değerin olmadığını göstermenizi sağlar. Biraz SQL'de NULL veya Objective-C'de NSNull gibi. "İlkel" tipler için bile kullanabileceğiniz için bu bir gelişme olacaktır.

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

Alıntı: Apple Inc. “Hızlı Programlama Dili”. iBooks. https://itun.es/gb/jEUH0.l


6
nilenum sabiti için sadece sözdizimsel şekerdir OptionalValue<T>.None( Tkullandığınız içeriğe uygun tip nerede nil). ?için bir kısayoldur OptionalValue<T>.Some(T).
rickster

4

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

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

1) Türden kesinlikle eminseniz, açmayı zorlamak için bir ünlem işareti kullanabilirsiniz, şöyle:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

İsteğe bağlı bir paketi açmaya zorlarsanız ve bu nil değerine eşitse, bu çökme hatasıyla karşılaşabilirsiniz:

resim açıklamasını buraya girin

Bu mutlaka güvenli değildir, bu nedenle tür ve değerden emin olmadığınız durumlarda çökmeyi önleyebilecek bir yöntem:

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

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

 if let unwrappedAge = age {

 // continue in here

 }

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

3) Muhafız beyanı

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

Buradan devam edip kaydırılmamış değişkeni kullanabilirsiniz. Değişkenin türünden eminseniz, yalnızca (!!

Projenizde iyi şanslar!


1

Öğrenmeye başladığımda Swiftneden isteğe bağlı olduğunu anlamak çok zordu .

Bu şekilde düşünelim. Bir sınıf düşünelim Personiki özelliği vardır nameve company.

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

Şimdi birkaç nesne oluşturalım Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

Ama biz geçemez Niliçinname

var personWithNoName:Person = Person.init(name: nil, company: nil)

Şimdi neden kullandığımız hakkında konuşalım optional?. Eklemek istediğiniz bir durum düşünün Lets Incgibi şirket adından sonra appleolacak apple Inc. IncŞirket adı ve baskıdan sonra eklememiz gerekiyor .

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

Şimdi isteğe bağlı olanın neden yer aldığını inceleyelim.

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Yerine Sağlar bobiletom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Ve Tebrikler! uygun şekilde anlaştıkoptional?

Yani gerçekleşme noktaları

  1. Mümkünse bir değişkeni isteğe bağlı olarak işaretleyeceğiz nil
  2. Bu değişkeni kod derleyicisinde bir yerde kullanmak istersek, içerdiğinde bu değişkenle uygun anlaşmamızın olup olmadığını kontrol etmemiz gerektiğini hatırlatacaktır nil.

Teşekkür ederim ... Mutlu Kodlama


0

Aşağıdaki kodu Playground.I umut deneyelim ne isteğe bağlı ve bunu kullanma nedeni açıklığa kavuşacaktır.

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil

0

Gönderen https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

İsteğe bağlı zincirleme, şu anda sıfır olabilecek bir isteğe bağlı özellikler, yöntemler ve abonelikleri sorgulama ve çağırma işlemidir. İsteğe bağlı bir değer içeriyorsa, özellik, yöntem veya alt simge çağrısı başarılı olur; isteğe bağlı nil ise, özellik, yöntem veya alt simge çağrısı nil değerini döndürür. Birden çok sorgu birlikte zincirlenebilir ve zincirdeki herhangi bir bağlantı boşsa tüm zincir zarif bir şekilde başarısız olur.

Daha derin anlamak için yukarıdaki bağlantıyı okuyun.


0

İyi...

? (İsteğe bağlı) değişkeninizin nil değeri içerebileceğini belirtir ! (paketleyici) çalışma zamanında değişkeninizin bir bellek (veya değer) kullanması (ondan bir değer almaya çalışılması) gerektiğini belirtir.

Temel fark, isteğe bağlı zincirleme, isteğe bağlı sıfır olduğunda zarif bir şekilde başarısız olurken, zorla açma işlemi isteğe bağlı sıfır olduğunda bir çalışma zamanı hatasını tetikler.

İsteğe bağlı zincirlemenin sıfır değerinde çağrılabileceği gerçeğini yansıtmak için, sorguladığınız özellik, yöntem veya alt simge isteğe bağlı olmayan bir değer döndürse bile, isteğe bağlı bir zincirleme çağrısının sonucu her zaman isteğe bağlı bir değerdir. Bu isteğe bağlı dönüş değerini, isteğe bağlı zincirleme çağrısının başarılı olup olmadığını (döndürülen isteğe bağlı bir değer içeriyorsa) veya zincirdeki bir nil değeri nedeniyle başarılı olup olmadığını (döndürülen isteğe bağlı değer nil) olup olmadığını kontrol etmek için kullanabilirsiniz.

Özellikle, isteğe bağlı bir zincirleme çağrısının sonucu, beklenen dönüş değeriyle aynı türdedir, ancak isteğe bağlı olarak sarılır. Normalde bir Int döndüren bir özellik bir Int? isteğe bağlı zincirleme yoluyla erişildiğinde.

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

İşte Apple Geliştirici Komitesi'nin temel öğreticisi: İsteğe Bağlı Zincirleme



-1

İşte Swift'de eşdeğer bir isteğe bağlı bildirim:

var middleName: String?

Bu bildirim String türünde middleName adlı bir değişken oluşturur. String değişkeni türünden sonraki soru işareti (?), MiddleName değişkeninin String veya nil olabilen bir değer içerebileceğini gösterir. Bu koda bakan herkes hemen middleName'nin nil olabileceğini bilir. Kendi kendini belgeliyor!

İsteğe bağlı bir sabit veya değişken için bir başlangıç ​​değeri belirtmezseniz (yukarıda gösterildiği gibi) değer sizin için otomatik olarak sıfır değerine ayarlanır. İsterseniz, ilk değeri açıkça nil olarak ayarlayabilirsiniz:

var middleName: String? = nil

daha fazla ayrıntı için isteğe bağlı aşağıdaki linki okuyun

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


Bunu kullan, var middleName: String! = ""
Gaurav
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.