Swift dilinde bir ünlem işareti ne anlama geliyor?


518

Swift Programlama Dili kılavuzunda aşağıdaki örnek bulunmaktadır:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

Daha sonra daireyi kişiye atarken, "örneği açmak" için bir ünlem işareti kullanırlar:

john!.apartment = number73

"Örneği açmak" ne anlama gelir? Neden gerekli? Sadece aşağıdakileri yapmaktan farkı nedir:

john.apartment = number73

Swift dilinde çok yeniyim. Sadece temelleri indirmeye çalýţýyorum.


GÜNCELLEME:
Eksik olduğum bulmacanın büyük parçası (cevaplarda doğrudan belirtilmemiş - en azından bunu yazarken değil):

var john: Person?

Aslında düşündüğüm gibi, " johntip Personve nil olabilir " anlamına gelmez . Ben sadece yanlış anladım Personve Person?tamamen ayrı tipler. Diğer tüm yani kavradığı zaman ?, !delilik ve aşağıda harika cevaplar, çok daha mantıklı.

Yanıtlar:


530

"Örneği açmak" ne anlama gelir? Neden gerekli?

Çalışabildiğim kadarıyla (bu benim için de çok yeni) ...

"Sarılı" terimi , isteğe bağlı bir değişkeni parlak kağıda sarılan (ne yazık ki!) Boş olabilecek bir hediye olarak düşünmemiz gerektiğini ima eder .

"Sarıldığında", İsteğe bağlı bir değişkenin değeri iki olası değere sahip bir numaralandır (biraz Boole gibi). Bu numaralandırma, değişkenin bir değer ( Some(T)) içerip içermediğini ( ) belirtir None.

Eğer bir değer varsa, bu değişkenin "paketinin açılması" (elde edilmesi ) ile elde Tedilebilir Some(T).

Nasıl john!.apartment = number73farklı gelen john.apartment = number73? (Aktarılan)

İsteğe bağlı bir değişkenin adını yazarsanız (örn., Metin johnolmadan !), bu değerin kendisini (T) değil, "sarılmış" numaralamayı (Bazıları / Hiçbiri) ifade eder. Yani johnbir örneği Persondeğil ve bir apartmentüyesi yok:

john.apartment
// 'Person?' does not have a member named 'apartment'

Gerçek Persondeğer çeşitli şekillerde açılabilir:

  • "zorla paketten çıkarma": john!( Personvarsa değeri verir, boşsa çalışma zamanı hatası verir)
  • "isteğe bağlı bağlama": if let p = john { println(p) }( printlndeğer varsa çalıştırır )
  • "isteğe bağlı zincirleme": john?.learnAboutSwift()(değer varsa bu tamamlama yöntemini yürütür)

Sıfır durumda ne olması gerektiğine ve bunun ne kadar olası olduğuna bağlı olarak, bu yollardan birini açmayı seçersiniz. Bu dil tasarımı nil kasasını açıkça ele almaya zorlar, ki bu da Obj-C (nil kasasını idare etmeyi unutmanın kolay olduğu) üzerindeki güvenliği arttırdığını varsayıyorum.

Güncelleme :

Ünlem işareti, sözdiziminde "Örtülü Olarak Açılmamış Seçenekler" bildirimi için de kullanılır.

Şimdiye kadarki örneklerde, johndeğişken olarak bildirilmiştir var john:Person?ve isteğe bağlıdır. Bu değişkenin gerçek değerini istiyorsanız, yukarıdaki üç yöntemden birini kullanarak değişkenin paketini açmalısınız.

var john:Person!Bunun yerine bildirilirse , değişken Örtük Olarak Açılmamış İsteğe Bağlı olacaktır (Apple'ın kitabındaki bu başlığa sahip bölüme bakın). Değere erişirken bu tür değişkenlerin paketini açmaya gerek yoktur ve johnek sözdizimi olmadan kullanılabilir. Ancak Apple'ın kitabı şöyle diyor:

Bir değişkenin daha sonraki bir noktada sıfır olma olasılığı varsa örtülü olarak kaydırılmamış seçenekler kullanılmamalıdır. Bir değişkenin ömrü boyunca sıfır değerini kontrol etmeniz gerekiyorsa, her zaman normal bir isteğe bağlı tür kullanın.

Güncelleme 2 :

Mike Ash'in " İlginç Swift Özellikleri " makalesi , isteğe bağlı türler için bazı motivasyon veriyor. Bence harika, net bir yazı.

Güncelleme 3 :

Ünlem işareti için örtük olarak açılmış isteğe bağlı kullanım hakkında başka bir yararlı makale : Chris Adamson tarafından " Swift ve Son Mil ". Makale bunun Apple tarafından, Objective-C çerçevelerinde kullanılan ve nil içerebilecek türlerin beyan edilmesinde kullanılan pragmatik bir önlem olduğunu açıklıyor. Bir türün isteğe bağlı (kullanılması ?) veya örtük olarak paketlenmemiş (kullanılması !) olarak bildirilmesi, "güvenlik ve rahatlık arasında bir denge" dir. Makalede verilen örneklerde, Apple, türleri örtülü olarak açılmamış olarak bildirmeyi seçerek arama kodunu daha uygun, ancak daha az güvenli hale getirdi.

Belki de Apple, gelecekte çerçevelerini gözden geçirerek, örtük olarak açılmamış ("muhtemelen asla sıfır") parametrelerin belirsizliğini ortadan kaldırabilir ve bunları isteğe bağlı ("kesinlikle [umarım belgelenmiş!] Koşullar") veya standart olmayanlarla değiştirebilir - Objective-C kodlarının tam davranışına dayanan isteğe bağlı ("asla sıfır") bildirimler.


Bu açıklamadan emin değilim. Eğer kodu sadece! yine de gerçek değeri döndürür. Belki ! hız için mi?
Richard Washington

TAMAM. Böylece dokümanlar kullanmaktan bahsediyorlar! emin olabilirsiniz, paketin açılmış olabileceğini. Ancak kodu olmadan o olmadan çalıştırabilirsiniz (listeniz için ileri bir seçenek - örtülü açma) VE önce kontrol etmeden. Değeri geri alırsınız veya nil ise nil. Ama nil olmadığından emin olursanız kullanın! ...... ama yine de neden bunu yapacağınızı göremiyorum?
Richard Washington

2
Merhaba @RichardWashington - Cevabıma bazılarını açıklığa kavuşturacak bir güncelleme ekledim.
Ashley

Güncelleme 3 tam olarak aradığım şey. Okumadan önce Apple'ın NSURLCredential gibi bir şey geri döndüğünde yalan söylediğini düşündüm! ki bu aslında sıfır olabilir.
Altın Başparmak

@Ashley harika cevap için teşekkürler. Bu yanıtı ve Apple'ın örnek hızlı kodunu okuduktan sonra, güvenlik ve verimlilik arasındaki bu dengede, genellikle daha güvenli tarafta olmak en iyisi gibi görünüyor. Bulduğum kayda değer bir istisna, Apple, UI öğeleri için zorla açmayı zorladığı zaman kullanmasıdır, çünkü birincisi, UI öğeleri bir storyboard dahil ederken genellikle isteğe bağlıdır (program olarak bir değer atanmadıkları için) ve ikincisi neredeyse içeren görünüm denetleyicisi nil olmadığı sürece hiçbir zaman sıfır, bu durumda bu tartışma tartışmalıdır.
Mihir

127

İşte fark olduğunu düşünüyorum:

var john: Person?

John olabilir olabilir anlamına gelir

john?.apartment = number73

Derleyici bu satırı şu şekilde yorumlar:

if john != nil {
    john.apartment = number73
}

Süre

john!.apartment = number73

Derleyici bu satırı basitçe şöyle yorumlayacaktır:

john.apartment = number73

Böylece, kullanarak! if ifadesinin paketini açar ve daha hızlı çalışmasını sağlar, ancak john nil ise, bir çalışma zamanı hatası ortaya çıkar.

Bu yüzden buraya sarın, belleğin sarıldığı anlamına gelmez, ancak kodun sarıldığı anlamına gelir, bu durumda bir if ifadesi ile sarılır ve Apple çalışma zamanında performansa çok dikkat ettiğinden, size bir yol vermek isterler. uygulamanızı mümkün olan en iyi performansla çalıştırın.

Güncelleme:

4 yıl sonra bu cevaba geri dönersek, Stackoverflow'da en yüksek itibarları aldım :) O zaman açılmanın anlamını biraz yanlış anladım. Şimdi 4 yıl sonra burada açmanın anlamının, kodu orijinal kompakt formundan genişletmek olduğuna inanıyorum. Ayrıca, tanımından nil ya da olmadığından emin olmadığımız için, o nesnenin etrafındaki belirsizliği kaldırmak anlamına gelir. Yukarıdaki Ashley'in cevabı gibi, bunu içinde hiçbir şey içermeyen bir hediye olarak düşünün. Ama yine de unwrapping enum kullanarak olarak kod çözme ve bellek tabanlı unwrapping değil düşünüyorum.


9
Oyun alanımda john.apartment = number73 derlenmez, john? 'U belirtmelisiniz .apartment = number73
Chuck Pinkert

2
@ChuckPinkert doğru, 4. satır john? .Apartment = number73, güzel cevap olsa düzenlenmelidir!
Bruce

john.apartment = number73 hata veriyor: İsteğe bağlı 'Kişi?' paketlenmemiş: '!' veya '?'
örümcek adam

4
Ambalajın açılmasının wrt performansı ile ilgisi yoktur. "Nil kontrolü" çalışma zamanında hala yapılmalıdır, tek fark isteğe bağlı herhangi bir değer yoksa bir çalışma zamanı hatası atılacak olmasıdır.
madidier

67

TL; DR

Swift dilinde bir ünlem işareti ne anlama geliyor?

Ünlem işareti etkili bir şekilde, “Bu isteğe bağlı kesinlikle bir değere sahip olduğunu biliyorum; lütfen kullanın. ” Bu, isteğe bağlı değerin zorla açılması olarak bilinir:

Misal

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

Kaynak: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399


11
Cevabınız harika çünkü şimdi neler olduğunu anlıyorum . Anlamadığım şey neden örtük olarak açılmamış seçeneklerin var olduğudur. Neden normal bir Dize türü yerine örtük olarak açılmamış isteğe bağlı bir Dize olarak tanımlanan bir şey oluşturmalısınız? Bundan sonra kullanımları aynıdır. Neyi kaçırıyorum?
pachun

Bu artık doğru gibi görünmüyor. Bir Swift 5 replinde, yaparsam let f: String! = "hello"ve sonra print(f), çıktı sadece Optional("hello")yerine "hello".
numbermaniac

37

John isteğe bağlı bir var olsaydı (bu şekilde beyan edildi)

var john: Person?

John'un değerinin olmaması (ObjC parlance, nil value)

Ünlem işareti temelde derleyiciye "Bunun bir değeri olduğunu biliyorum, test etmenize gerek yok" der. Kullanmak istemediyseniz, şartlı olarak test edebilirsiniz:

if let otherPerson = john {
    otherPerson.apartment = number73
}

Bunun içi sadece john'un bir değeri olup olmadığını değerlendirecektir.


4
Yanıt için teşekkürler, şimdi ünlem işaretinin ne dediğini anlıyorum , hala kafamı neden etrafına sarmaya çalışıyorum ... Derleyiciye "Bunun bir değeri olduğunu biliyorum, test etmene gerek olmadığını söyledin o". Derleyici bunu test etmediğinde beni ne satın alıyor? Ünlem işareti olmadan, derleyici bir hata atacak mı (henüz bir ortamım yok, Swift'i nerede test edebileceğim)? Öyle mi? Tüm isteğe bağlı değişkenler için% 100 gerekli mi? Eğer öyleyse, neden bu kadar eksikliği yapmak yerine Apple neden rahatsız etti ! "Bunun bir değeri olduğunu biliyorum, test etmenize gerek yok" mu?
Troy

"derleyici bir hata atacak" - hayır hala değeri beklendiği gibi döndürerek iyi çalışıyor. Bunu anlamıyorum. Öyle mi? sadece hız için emin olabilirsiniz belki?
Richard Washington

Aslında daha sonra dokümanlar, aşağıdaki örneği kullanarak örtük olarak kaydırılmamış seçeneklerden bahseder: “let possibleString: String? = "An optional string." println(possibleString!) // requires an exclamation mark to access its value // prints "An optional string.” Ama hayır! Burada bir şey tuhaf görünüyor.
Richard Washington

3
@RichardWashington İyi bir nedenden dolayı kafan karıştı! Dokümanlardaki örnekler bazı şeyleri dışarıda bırakıyor ve yanıltıcıdır çünkü tek yaptıkları println kullanmaktır. Görünüşe göre, opsiyonelleri açmanın gerekli olmadığı en az birkaç örnek var. Bunlardan biri println kullanılırken. Bir diğeri dize enterpolasyonu kullanmaktır. Yani, belki println ve string enterpolasyonu örtülerin altından çıkar? Belki birisi bunun hakkında daha fazla bilgiye sahiptir. Xcode6 Beta başlık tanımlarına bakmak bana bu sihir hakkında hiçbir şey açıklamadı.
mbeaty

Evet, anladım John?ve Johniki farklı tip. Biri İsteğe Bağlı Kişi, diğeri Tip Kişi'dir. Kişiyi dışarı çıkarabilmeniz için isteğe bağlı Kişi'nin paketinin açılması gerekir. Ama dediğin gibi, bu en azından bu koşullarda gerçekte hiçbir şey yapmadan gerçekleşiyor gibi görünüyor. Bu yapmak gibi görünüyor! yedekli. Tabii! DAİMA isteğe bağlıdır, ancak derleme zamanı hatalarını yakalamak için yapılması önerilen bir şeydir. Belirli bir tür için vars / lets atama gibi bir tür açık let John: Person = ...olabilir, ancak çıkartılabilir let John = ....
Richard Washington

27

Diğer faydalı ancak daha ayrıntılı merkezli cevaplara eklemek için bazı büyük resim perspektifi:

Swift'te, ünlem işareti birkaç bağlamda görünür:

  • Zorla açma: let name = nameLabel!.text
  • Örtük olarak paketlenmemiş opsiyonel öğeler: var logo: UIImageView!
  • Zorla döküm: logo.image = thing as! UIImage
  • İşlenmeyen istisnalar: try! NSJSONSerialization.JSONObjectWithData(data, [])

Bunların her biri farklı bir anlama sahip farklı bir dil yapısıdır, ancak hepsinin ortak üç önemli yanı vardır:

1. Ünlem noktaları Swift'in derleme zamanı güvenlik kontrollerini atlatır.

!Swift'te kullandığınızda , aslında, “Hey, derleyici, burada bir hata olabileceğini düşündüğünüzü biliyorum , ama bunun kesinlikle olmayacağını kesinlikle biliyorum .” Diyorsunuz.

Geçerli kodların tümü, Swift'in derleme zamanı tür sistemi veya herhangi bir dilin statik tür denetimi kutusuna sığmaz . Bir hatanın asla olmayacağını mantıksal olarak kanıtlayabileceğiniz durumlar vardır, ancak derleyiciye kanıtlayamazsınız . Bu yüzden Swift tasarımcıları bu özellikleri en başta ekledi.

Ancak, ne zaman kullanırsanız kullanın !, bir hata için bir kurtarma yoluna sahip olmaya karar verirsiniz, yani ...

2. Ünlem işaretleri potansiyel çökmelerdir.

Ünlem işareti aynı zamanda “Swift Hey ben diyor böylece bu hata için daha iyi olduğunu asla olamaz emin benim bütün app çökmesine bunun için bir kurtarma yolu koduna benden çok.”

Bu tehlikeli bir iddia. Doğru olabilir : Kodunuzun değişmezleri hakkında çok düşündüğünüz kritik görev kodunda, sahte çıktının bir çökmeden daha kötü olması olabilir.

Ancak, !vahşi doğada gördüğümde , nadiren çok dikkatli kullanılır. Bunun yerine, sık sık, "bu değer isteğe bağlıydı ve neden nil olabileceği veya bu durumu düzgün bir şekilde nasıl ele alacağı hakkında çok fazla düşünmedim , ancak ekleme !derlendi ... yani kodum doğru, değil mi?"

Ünlem işaretinin kibirli olmasına dikkat edin. Yerine…

3. Ünlem işaretleri en iyi şekilde az kullanılır.

Bu !yapıların her birinde, ?sizi error / nil davasıyla başa çıkmaya zorlayan bir karşılığı vardır:

  • Koşullu açma: if let name = nameLabel?.text { ... }
  • İsteğe bağlı maddeler: var logo: UIImageView?
  • Koşullu yayınlar: logo.image = thing as? UIImage
  • Hata durumunda Nil istisnaları: try? NSJSONSerialization.JSONObjectWithData(data, [])

!Kullanmak için cazip iseniz, ?bunun yerine neden kullanmadığınızı dikkatlice düşünmek her zaman iyidir . !İşlem başarısız olursa , programınızı çökertmek gerçekten en iyi seçenek midir? Bu değer neden isteğe bağlı / faiable?

Kodunuzun nil / error durumunda alabileceği makul bir kurtarma yolu var mı? Varsa kodlayın.

Büyük olasılıkla sıfır olamazsa, hata asla gerçekleşemezse, derleyicinin bunu bilmesi için mantığınızı yeniden çalışmanın makul bir yolu var mı? Eğer öyleyse yapın; kodunuz daha az hataya açık olacaktır.

Bir hatayı işlemek için makul bir yolun olmadığı ve hatayı görmezden gelmenin ve dolayısıyla yanlış verilerle devam etmenin - çökmekten daha kötü olduğu zamanlar vardır. Bunlar kuvvet açmanın kullanılma zamanıdır.

Düzenli olarak tüm kod tabanımı arar !ve her kullanımını denetlerim . Çok az kullanım incelemeye dayanır. (Bu yazıdan itibaren, tüm Siesta çerçevesinin tam olarak iki örneği vardır .)

Bu , kodunuzda asla kullanmamanız gerektiği anlamına gelmez! - sadece onu dikkatli bir şekilde kullanmanız ve asla varsayılan seçenek yapmamanız gerekir .


func isSubscriptionActive(receiptData: NSDictionary?) -> Bool { if(receiptData == nil) { return false; } return (hasValidTrial(receiptData!) || isNotExpired(receiptData!)) && isNotCancelled(receiptData!) } Verilen 3. yazmanın daha iyi bir yolu var mı?
jenson-button-event

func isSubscriptionActive(receiptData: NSDictionary?) -> Bool { guard let nonNilReceiptData = receiptData else { return false} return (hasValidTrial(nonNilReceiptData) || isNotExpired(nonNilReceiptData)) && isNotCancelled(nonNilReceiptData) }
Şunu

Ünlem işaretleri güvenlik kontrollerini atlatmaz. İsteğe bağlı sıfır ise garantili bir kilitlenme alırsınız . İsteğe bağlı daima kontrol edilir. Güvenlik kontrolü yapmanın çok acımasız bir yolu.
gnasher729

@ gnasher729 Yanıtın belirttiği gibi, derleme zamanı güvenlik denetimlerini güvenli bir çalışma zamanı hatası lehine atlar .
Paul Cantrell

24

johnisteğe bağlıdır var. Yani bir nildeğer içerebilir . Değerin sıfır olmadığından emin olmak !için varadın sonunda a kullanın .

Belgelerden

“İsteğe bağlı bir değer içerdiğinden emin olduktan sonra, isteğe bağlı adının sonuna bir ünlem işareti (!) Ekleyerek temel değerine erişebilirsiniz. Ünlem işareti etkili bir şekilde, “Bu isteğe bağlı kesinlikle bir değere sahip olduğunu biliyorum; lütfen kullanın. ”

Sıfır olmayan değeri kontrol etmenin bir başka yolu da

    if let j = json {
        // do something with j
    }

1
Evet, bunu dokümantasyonda görmüştüm, ama yine de gereksiz görünüyor ... bana göre, john.apartment = number73"Bu isteğe bağlı kesinlikle bir değere sahip olduğunu biliyorum; lütfen kullanın." ...
Troy

6
Evet, ama önemli olan nokta Swift'in derleme zamanında hataları yakalamaya çalışmasıdır. Bu değişkenin nil içeremeyeceğini biliyorsanız veya bildiğinizi düşünüyorsanız, ünlem işaretini kullanarak bu denetimi kaldırabilirsiniz.
lassej

16

İşte bazı örnekler:

var name:String = "Hello World"
var word:String?

wordİsteğe bağlı bir değer nerede . bir değer içerebileceği veya içermeyebileceği anlamına gelir.

word = name 

Burada namebir değer var, böylece atayabiliriz

var cow:String = nil
var dog:String!

dogZorla açılmamış yerlerde , bir değer içermesi gerektiği anlamına gelir

dog = cow

Paketlenmemiş olarak atandığımız niliçin uygulama çökecek


1
var c:Int = nilalacak: "Nil belirtilen 'int' türünü başlatamıyor"
Asususer

15

Bu durumda...

var John: Kişi!

bu, başlangıçta John'un nil değerine sahip olacağı, ayarlanacağı ve bir kez ayarlandığında bir daha asla nil liderliği olmayacağı anlamına gelir. Bu nedenle, kolaylık sağlamak için isteğe bağlı bir varlığa erişmek için daha kolay sözdizimini kullanabilirim, çünkü bu bir "Örtülü olarak paketlenmemiş isteğe bağlı"


1
Teşekkür ederim. Bunu açıklayan aşağıdaki bağlantıyı da buldum. Bu tür türlere "örtük olarak açılmamış seçenek" denir. stackoverflow.com/questions/24122601/…
Kaydell

5

Bir C-aile dilinden geldiyseniz, "bellek türü 0 (NULL) olabilecek X türü nesneye işaretçi" olarak düşüneceksiniz ve dinamik olarak yazılmış bir dilden geliyorsanız, "Muhtemelen X tipi olan, ancak tanımsız tipte olabilecek nesne" diye düşünüyor. Bunların hiçbiri aslında doğru değil, dolambaçlı bir şekilde birincisi yakın.

Düşünmeniz gereken şey sanki bir nesne gibi:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

İsteğe bağlı değerinizi foo == nilgerçekten geri döndüğünü test foo.isNilederken ve foo!bunun foo.realObjectbir iddia ile geri döndüğünü söylediğinizde foo.isNil == false. Bunu not etmek önemlidir, çünkü fooaslında bunu yaparken nil ise foo!, bu bir çalışma zamanı hatasıdır, bu nedenle değerin sıfır olmayacağından emin olmadığınız sürece, genellikle koşullu bir izin kullanmak istersiniz. Bu tür bir hile, dilin, değerlerin her yerde sıfır olup olmadığını test etmeye zorlamadan güçlü bir şekilde yazılabileceği anlamına gelir.

Pratikte, gerçekten böyle davranmaz çünkü iş derleyici tarafından yapılır. Yüksek düzeyde Foo?ayrı olan Foove türü kabul eden işlevlerin Foosıfır değeri almasını engelleyen bir tür vardır , ancak düşük düzeyde isteğe bağlı bir değer gerçek bir nesne değildir çünkü özellikleri veya yöntemleri yoktur; aslında zorla açarken uygun test ile NULL (0) ile bir işaretçi olabilir.

Bir ünlem işaretinin türde olduğunu göreceğiniz başka bir durum vardır, örneğin:

func foo(bar: String!) {
    print(bar)
}

Bu kabaca bir açma / kapama ile isteğe bağlı kabul etmekle eşdeğerdir, yani:

func foo(bar: String?) {
    print(bar!)
}

Teknik olarak isteğe bağlı bir değeri kabul eden, ancak sıfırsa bir çalışma zamanı hatası olacak bir yöntem elde etmek için bunu kullanabilirsiniz. Swift'in mevcut sürümünde bu görünüşte is-nil iddiasını atlıyor, böylece bunun yerine düşük seviyeli bir hata olacaksınız. Genellikle iyi bir fikir değildir, ancak kodu başka bir dilden dönüştürürken yararlı olabilir.



3

C # hakkında bilginiz varsa, bu aynı zamanda bir soru işareti kullanılarak bildirilen Nullable türleri gibidir:

Person? thisPerson;

Ve bu durumda ünlem işareti, nullable türünün .Value özelliğine şu şekilde erişmeye eşdeğerdir:

thisPerson.Value

2

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, farklı türlerde değişkenler atamaktan oluşan hataların önüne geçer.

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

 {..}

2

! bir nesnenin sonunda, nesnenin isteğe bağlı olduğunu ve aksi takdirde sıfır döndürüp döndüremeyeceğini çözeceğini söyler. Bu genellikle, programın çökmesine neden olacak hataları yakalamak için kullanılır.


2

Kısaca (!): Bir değişken bildirdikten ve değişkenin bir değer tuttuğundan emin olduktan sonra.

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

aksi takdirde değeri geçtikten sonra bunu yapmanız gerekir ...

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark

1

John, isteğe bağlı bir Kişidir, yani bir değeri tutabilir veya sıfır olabilir.

john.apartment = number73

john isteğe bağlı değilse kullanılır. John asla nil olduğundan biz bir nil değeri daire çağırmayacağından emin olabilirsiniz. Süre

john!.apartment = number73

derleyiciye john nil olmadığına dair söz verir, daha sonra john'un değerini almak için opsiyonel olanı açar ve john'un apartman mülküne erişir. John'un sıfır olmadığını biliyorsanız bunu kullanın. Bunu isteğe bağlı olarak nil olarak çağırırsanız, bir çalışma zamanı hatası alırsınız.

Belgelendirme, convertedNumber'ın isteğe bağlı olduğu yerlerde kullanmak için güzel bir örnek içerir.

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}

Eğer john nil ise ve ben gidersem john.apartment = number73, '!' john sonra?
Troy

John isteğe bağlı ise, özelliklerine erişmek için ünlem noktasını kullanmalısınız çünkü derleyici sıfır olmadığını bilmelidir. İsteğe bağlı değilse ünlem işaretini kullanamazsınız.
Connor

1
TÜM isteğe bağlı değişkenler için bir ünlem işareti kullanmam gerekiyorsa, Apple neden bir ünlem noktasının olmaması aynı şey anlamına geldiği için bununla uğraştı? Gereksiz şişkinlik gibi görünüyor ... Yoksa isteğe bağlı bir var ile bir ünlem işareti KULLANMAMAN mantıklı bir durum var mı?
Troy

isteğe bağlı olarak nil olmamasına ihtiyaç duyduğunuzda ünlem işaretini kullanırsınız. John'un özelliklerine erişme durumunda olduğu gibi. var jack gibi bir şey yapabilirdin: Kişi? = john burada jack da isteğe bağlı veya var jack: Kişi = john! jack bir kişidir ve sıfır değildir
Connor

Doğru ama, orijinal örnekte, johnisteğe bağlı olarak kayıttan çıkarma yaptığım gerçeği , derleyiciye sıfır olmamasına ihtiyacım olduğunu söylemiyor mu? ... Ve var jack: Person = john!örneğinizde, bir eksikliği yok mu? Kişi derleyiciye johnsıfır olmayan gerektiğini söyledi sonra? Genel olarak, !sadece biraz gereksiz gibi görünüyor ... Hala "neden" kısmında bir şey eksik gibi hissediyorum !...
Troy

1

Basitçe söylemek gerekirse, ünlem işaretleri isteğe bağlı bir paketin açıldığı anlamına gelir. İsteğe bağlı, bir değere sahip olan veya olmayan bir değişkendir - bu nedenle, burada gösterildiği gibi bir if let ifadesi kullanarak değişkenin boş olup olmadığını kontrol edebilir ve ardından sıkıştırmayı açmaya zorlayabilirsiniz. Boş bir isteğe bağlı paketini açmaya zorlarsanız, programınız çökecektir, bu yüzden dikkatli olun! Opsiyonel, bir değişkene açık bir atamanın sonuna bir soru işareti koyarak bildirilir, örneğin yazabilirim:

var optionalExample: String?

Bu değişkenin değeri yoktur. Eğer paketini açacak olsaydım, program çökecek ve Xcode size isteğe bağlı bir nil değeri açmaya çalışacağınızı söyleyecekti.

Umut etmek bu yardım etmek.


1

BASİT SÖZLERDE

KULLANIM Ünlem işareti, değişkenin sıfır olmayan değer içermesi gerektiğini belirtir (asla sıfır değildir)


1

Tüm hikaye isteğe bağlı değişkenler adı verilen hızlı bir özellik ile başlar. Bunlar, bir değeri olabilen veya bir değeri olmayan varslardır. Genel olarak swift, başlatılmayan bir değişkeni kullanmamıza izin vermez, çünkü bu çökmelere veya beklenmedik nedenlere ve ayrıca arka kapılar için bir yer tutucusuna neden olabilir. Dolayısıyla, değeri başlangıçta belirlenmemiş olan bir değişkeni bildirmek için '?' Kullanırız. Böyle bir değişken bildirildiğinde, bunu kullanmadan önce bazı ifadelerin bir parçası olarak kullanmak için, paketin açılması, değişkenin değerinin nesneler için geçerli olduğu keşfedilen bir işlemdir. Bunları kullanmaya çalışırsanız açmadan derleme zamanı hatası alırsınız. İsteğe bağlı bir değişken olan bir değişkeni açmak için ünlem işareti "!" kullanıldı.

Şimdi bu tür isteğe bağlı değişkenlerin sistem tarafından örneğin veya kendi programınızla ancak bir süre sonra, örneğin UI çıkışları gibi bir soru işareti "?" kullanırız "!".

Böylece sistem bilir ki bu "!" şu anda isteğe bağlıdır ve değeri yoktur, ancak daha sonra kullanım ömrü içinde bir değer alır.

Böylece ünlem işareti iki farklı kullanım içerir: 1. İsteğe bağlı olacak ve kesinlikle daha sonra değer alacak bir değişkeni bildirmek için 2. Bir ifadede kullanmadan önce isteğe bağlı bir değişkeni açmak.

Yukarıdaki açıklamaların çok fazla teknik şeyden kaçındığını umuyorum.


1

İsteğe bağlı olarak kullanırsanız, isteğe bağlı olanın paketini açar ve orada bir şey olup olmadığını görür. Eğer if-else deyiminde kullanırsanız NOT kodudur. Örneğin,

if (myNumber != 3){
 // if myNumber is NOT 3 do whatever is inside these brackets.
)

1

İsteğe bağlı bir değişken bir değer içerebilir veya içermeyebilir

dava 1: var myVar:String? = "Something"

durum 2: var myVar:String? = nil

şimdi myVar! "Something"

2 durumunda çökecektir.

Anlam! işareti, derleyici orada olmasa bile bir değer döndürmeye zorlar. bu yüzden kuvvet açmaya zorla .


@Moritz. Bilmiyorum öyle mi? Bir soru zaten cevaplandıysa cevap veremez miyim? Herhangi bir soruna neden oluyor muyum yoksa cevabımda bir sorun var mı? i anlamıyorum Neden doğru cevap verdiğin için aşağı indiriyorsun? Kavram konusundaki anlayışım temelinde cevap vermeye çalıştım. bazı insanların açık ve kolay bir açıklama için yararlı bulacağını düşünüyorum.
Ashish Pisey

@Moritz Şimdi bu yapıcı. Bu düzeltmeyi ilk başta söylemeliydin, eğer sebep buysa. Geri dönüşünüz için teşekkür ederiz. ben düzelttim.
Ashish Pisey

0
Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String

1
Lütfen daha önce yanıtlanmamış olan hiçbir şey eklemeyen cevaplar yazmayın.
Dalija Prasnikar

-1

KENDİNE SOR

  • Türün person?bir apartmentüyesi / mülkü var mı? VEYA
  • Türün personbir apartmentüyesi / mülkü var mı?

Bu soruya cevap veremiyorsanız okumaya devam edin:

Anlamak için Generics'in çok temel düzeyde anlaşılması gerekebilir . Buraya bakın . Swift'teki birçok şey Generics kullanılarak yazılmıştır. Seçenek dahil

Aşağıdaki kod bu Stanford videosundan sağlanmıştır . İlk 5 dakikayı izlemenizi şiddetle tavsiye ederim

İsteğe bağlı sadece 2 vaka içeren bir numaralandırmadır

enum Optional<T>{
    case None
    case Some(T)
}

let x: String? = nil //actually means:

let x = Optional<String>.None

let x :String? = "hello" //actually means:

let x = Optional<String>.Some("hello")

var y = x! // actually means:

switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}

İsteğe bağlı ciltleme:

let x:String? = something
if let y = x {
    // do something with y
}
//Actually means:

switch x{
case .Some(let y): print)(y) // or whatever else you like using 
case .None: break
}

var john: Person?Aslında böyle demek istediğinizi söylediğinizde :

enum Optional<Person>{
case .None
case .Some(Person)
}

Yukarıdaki numaralandırma adlı herhangi bir özelliğe sahip apartmentmi? Herhangi bir yerde görüyor musun? Hiç orada değil ! Ancak, paketini person!açarsanız, yani ... kaputun altında ne yapar:Optional<Person>.Some(Person(name: "John Appleseed"))


var john: PersonBunun yerine şunları tanımlamış var john: Person?olsaydınız : artık kullanmanıza gerek kalmazdı !çünkü Personkendisinin bir üyesi varapartment


Gelecekte neden !açmak için kullanmanın bazen tavsiye edilmediğine dair bir tartışma olarak bu Soru-Cevap bölümüne bakın


2
Yukarıdaki gerçek slaytları kullanmak muhtemelen telif hakkı ihlalidir: "... Stanford Üniversitesi iTunes U koleksiyonumuzdaki tüm içeriğin telif hakkını elinde tutar." , http://itunes.stanford.edu . Bu soruyu cevaplamayı düşündüğünüz dersten öğrendiğiniz içeriği kendi kelimelerinizle cevaplamak muhtemelen daha iyidir (ve slaytları kullanmak yerine , bunların ilgili kısımlarını kod biçiminde, doğal olarak referanslarla alıntılayın ).
dfri

2
Argümanınız argümanum reklam popülasyonudur . Her neyse, Stanford'un buraya geleceğine ve DMCA haklarını uygulayacağına inanmıyorum , ancak cevaplarınız resmi / geçerli kaynaklara dayalı kendi kelimelerinizdeyse ve bu kaynakları yukarıdaki gibi doğrudan kopyalamak şeklinde değilse her zaman daha iyidir ; özellikle telif hakkıyla korunan slaytlar hakkında konuştuğumuzda: yine, kod bloklarındaki slaytların içeriğini alıntılamak daha iyidir (kod görüntüleri genellikle burada SO-hayır!
dfri

1
Bağlantı kurduğum meta yazı sadece SO: s yaklaşımını şöyle anlatıyor: bazı rasgele kullanıcı bunu telif hakkı ihlali olarak rapor ederse doğal olarak kaldırılmayacak: sadece örneğin bir Stanford temsilcisi. Buraya gelmek ve kaldırılacak yazı çok zorlamak gerekir gibi. Bu yüzden " Stanford'un buraya gelip DMCA haklarını uygulayacağına inanmıyorum ..." diye yazdım . Yukarıdaki nokta, bunun muhtemelen telif hakkı ihlali olduğuna inanıyorum (ki bunun yanlış olduğuna inanıyorum), ancak doğal olarak hiç kimse bunu zorlamayacaktır. ...
dfri

1
Ancak bu bir yana, kod görüntülerini içeren soruların veya cevapların gönderilmesi çeşitli nedenlerden dolayı caydırılır . Özetlemek gerekirse: Bu cevabın şu anki haliyle, iki önemli nedenden dolayı (telif hakkı olan slaytlar, kodun görüntüsü) olabildiğince iyi olmadığına inandığım bu yorumları işaret etmeye çalıştım. Doğal olarak, kendim de dahil olmak üzere hiç kimse bu konuda hiçbir şey yapmayacak, sadece referans olarak geleceğimizi işaret ediyorum (veya muhtemelen bu yazıyı kod bloklarıyla alıntı ile düzenlemenizi teşvik ediyorum). Kabul, iTunes U! :)
dfri

2
@dfri kaldırıldı görüntüleri
Bal
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.