Swift Language
optionals
Zoeken…
Invoering
"Een optionele waarde bevat een waarde of bevat nul om aan te geven dat een waarde ontbreekt"
Fragment uit: Apple Inc. "The Swift Programming Language (Swift 3.1 Edition)." iBooks. https://itun.es/us/k5SW7.l
Standaard optionele use cases zijn: voor een constante (let), gebruik van een optionele binnen een lus (if-let), het veilig uitpakken van een optionele waarde binnen een methode (guard-let), en als onderdeel van schakelaarlussen (case-let ), standaard ingesteld op nul, met de coalesce-operator (??)
Syntaxis
- var optioneelNaam: optioneelType? // declareer een optioneel type, standaard nul
- var optioneelNaam: optioneelType? = waarde // declareer een optioneel met een waarde
- var optioneelNaam: optioneelType! // verklaar een impliciet onverpakte optie
- optioneel! // forceer een optioneel uitpakken
Opmerkingen
Zie De snelle programmeertaal voor meer informatie over opties.
Soorten opties
Optionals zijn een generiek enum-type dat fungeert als een wrapper. Met deze wrapper kan een variabele een van twee toestanden hebben: de waarde van het door de gebruiker gedefinieerde type of nil
, wat de afwezigheid van een waarde vertegenwoordigt.
Dit vermogen is vooral belangrijk in Swift omdat een van de genoemde ontwerpdoelstellingen van de taal is om goed te werken met de frameworks van Apple. Veel (de meeste) van Apple's frameworks gebruiken nil
vanwege het gebruiksgemak en de betekenis voor programmeerpatronen en API-ontwerp binnen Objective-C.
In Swift moet een variabele een nil
hebben om een variabele te zijn. Optionele opties kunnen worden gemaakt door een a toe te voegen !
of een ?
naar het variabele type. Als u bijvoorbeeld een Int
optioneel wilt maken, kunt u gebruiken
var numberOne: Int! = nil
var numberTwo: Int? = nil
?
Optionals moeten expliciet worden uitgepakt en moeten worden gebruikt als u niet zeker weet of de variabele een waarde heeft wanneer u deze opent. Wanneer u bijvoorbeeld een string in een Int
, is het resultaat een optionele Int?
, omdat nul wordt geretourneerd als de string geen geldig getal is
let str1 = "42"
let num1: Int? = Int(str1) // 42
let str2 = "Hello, World!"
let num2: Int? = Int(str2) // nil
!
Optionals worden automatisch uitgepakt en mogen alleen worden gebruikt als u zeker weet dat de variabele een waarde heeft wanneer u deze opent. Bijvoorbeeld een wereldwijde UIButton!
variabele die wordt geïnitialiseerd in viewDidLoad()
//myButton will not be accessed until viewDidLoad is called,
//so a ! optional can be used here
var myButton: UIButton!
override func viewDidLoad(){
self.myButton = UIButton(frame: self.view.frame)
self.myButton.backgroundColor = UIColor.redColor()
self.view.addSubview(self.myButton)
}
Optioneel uitpakken
Om toegang te krijgen tot de waarde van een Optioneel, moet deze worden uitgepakt.
U kunt voorwaardelijk uitpakken een optionele met behulp van optionele binding en kracht uitpakken een optionele gebruik van de !
operator.
Voorwaardelijk uitpakken vraagt effectief "Heeft deze variabele een waarde?" terwijl Force Unpacking zegt: "Deze variabele heeft een waarde!".
Als je een variabele die nil
is, nil
, gooit je programma een onverwacht gevonden nul terwijl een optionele uitzondering en crash wordt uitgeschakeld, dus je moet goed overwegen of je deze gebruikt !
is gepast.
var text: String? = nil
var unwrapped: String = text! //crashes with "unexpectedly found nil while unwrapping an Optional value"
Voor veilig uitpakken kunt u een if-let
instructie gebruiken, die geen uitzondering genereert of crasht als de verpakte waarde nil
:
var number: Int?
if let unwrappedNumber = number { // Has `number` been assigned a value?
print("number: \(unwrappedNumber)") // Will not enter this line
} else {
print("number was not assigned a value")
}
var number: Int?
guard let unwrappedNumber = number else {
return
}
print("number: \(unwrappedNumber)")
Merk op dat het bereik van de variabele unwrappedNumber
zich binnen de if-let
instructie en buiten het guard
.
U kunt het uitpakken van veel optionele opties koppelen, dit is vooral handig in het geval dat uw code meer dan variabele vereist om correct te worden uitgevoerd:
var firstName:String?
var lastName:String?
if let fn = firstName, let ln = lastName {
print("\(fn) + \(ln)")//pay attention that the condition will be true only if both optionals are not nil.
}
Merk op dat alle variabelen moeten worden uitgepakt om met succes de test te doorstaan, anders zou je geen manier hebben om te bepalen welke variabelen werden uitgepakt en welke niet.
U kunt voorwaardelijke verklaringen aan elkaar koppelen met behulp van uw optionele opties onmiddellijk nadat deze zijn uitgepakt. Dit betekent geen geneste als - anders verklaringen!
var firstName:String? = "Bob"
var myBool:Bool? = false
if let fn = firstName, fn == "Bob", let bool = myBool, !bool {
print("firstName is bob and myBool was false!")
}
Nul Coalescing Operator
U kunt de nul-coalescentie-operator gebruiken om een waarde uit te pakken als deze niet nul is, anders een andere waarde opgeven:
func fallbackIfNil(str: String?) -> String {
return str ?? "Fallback String"
}
print(fallbackIfNil("Hi")) // Prints "Hi"
print(fallbackIfNil(nil)) // Prints "Fallback String"
Deze operator kan kortsluiten , wat betekent dat als de linkeroperand niet nul is, de rechteroperand niet wordt geëvalueerd:
func someExpensiveComputation() -> String { ... }
var foo : String? = "a string"
let str = foo ?? someExpensiveComputation()
In dit voorbeeld wordt foo
niet-nul genoemd, someExpensiveComputation()
niet wordt aangeroepen.
U kunt ook meerdere nulcoalescentieverklaringen aan elkaar koppelen:
var foo : String?
var bar : String?
let baz = foo ?? bar ?? "fallback string"
In dit voorbeeld krijgt baz
de onverpakte waarde van foo
toegewezen als deze niet nul is, anders krijgt het de onverpakte waarde van bar
als deze niet nul is, anders krijgt het de fallback-waarde toegewezen.
Optioneel koppelen
U kunt Optioneel koppelen gebruiken om een methode aan te roepen, een eigenschap te openen of een optioneel abonnement te nemen . Dit doet u door een ?
tussen de gegeven optionele variabele en het gegeven lid (methode, eigenschap of subscript).
struct Foo {
func doSomething() {
print("Hello World!")
}
}
var foo : Foo? = Foo()
foo?.doSomething() // prints "Hello World!" as foo is non-nil
Als foo
een waarde bevat, wordt doSomething()
aangeroepen. Als foo
nil
, zal er niets slechts gebeuren - de code zal gewoon stil mislukken en doorgaan met uitvoeren.
var foo : Foo? = nil
foo?.doSomething() // will not be called as foo is nil
(Dit is vergelijkbaar met het verzenden van berichten naar nil
in Objective-C)
De reden dat Optioneel koppelen als zodanig wordt genoemd, is omdat 'optionality' wordt verspreid via de leden die u belt / toegang hebt. Dit betekent dat de retourwaarden van alle leden die worden gebruikt met optionele koppeling, optioneel zijn, ongeacht of ze als optioneel zijn getypt of niet.
struct Foo {
var bar : Int
func doSomething() { ... }
}
let foo : Foo? = Foo(bar: 5)
print(foo?.bar) // Optional(5)
Hier foo?.bar
retourneert een Int?
hoewel bar
niet-optioneel is, omdat foo
zelf optioneel is.
Als optie wordt gepropageerd, zullen methoden die Void
retourneren Void
retourneren Void?
wanneer opgeroepen met optionele ketting. Dit kan handig zijn om te bepalen of de methode al dan niet is aangeroepen (en dus of de optie een waarde heeft).
let foo : Foo? = Foo()
if foo?.doSomething() != nil {
print("foo is non-nil, and doSomething() was called")
} else {
print("foo is nil, therefore doSomething() wasn't called")
}
Hier vergelijken we de Void?
retourneer de waarde met nil
om te bepalen of de methode is aangeroepen (en dus of foo
niet-nul is).
Overzicht - Waarom Optionals?
Vaak is het bij het programmeren nodig om een onderscheid te maken tussen een variabele die een waarde heeft en een die dat niet heeft. Voor referentietypen, zoals C-pointers, kan een speciale waarde zoals null
worden gebruikt om aan te geven dat de variabele geen waarde heeft. Voor intrinsieke typen, zoals een geheel getal, is het moeilijker. Een genomineerde waarde, zoals -1, kan worden gebruikt, maar dit is afhankelijk van de interpretatie van de waarde. Het elimineert ook die "speciale" waarde van normaal gebruik.
Om dit aan te pakken, staat Swift toe dat elke variabele als optioneel wordt gedeclareerd. Dit wordt aangegeven door het gebruik van een? of! na het type (zie Soorten opties )
Bijvoorbeeld,
var possiblyInt: Int?
declareert een variabele die al dan niet een geheel getal bevat.
De speciale waarde nil
geeft aan dat er momenteel geen waarde is toegewezen aan deze variabele.
possiblyInt = 5 // PossiblyInt is now 5
possiblyInt = nil // PossiblyInt is now unassigned
nil
kan ook worden gebruikt om te testen op een toegewezen waarde:
if possiblyInt != nil {
print("possiblyInt has the value \(possiblyInt!)")
}
Let op het gebruik van !
in de print-opdracht om de optionele waarde uit te pakken .
Als een voorbeeld van een algemeen gebruik van opties, kunt u een functie overwegen die een geheel getal retourneert uit een tekenreeks die cijfers bevat; Het is mogelijk dat de string niet-cijferige tekens bevat, of zelfs leeg is.
Hoe kan een functie die een eenvoudige Int
retourneert een fout aangeven? Het kan dit niet doen door een specifieke waarde te retourneren, omdat deze zou voorkomen dat die waarde uit de string wordt geparseerd.
var someInt
someInt = parseInt("not an integer") // How would this function indicate failure?
In Swift kan die functie echter eenvoudig een optionele Int retourneren. Dan wordt falen aangegeven met de retourwaarde nil
.
var someInt?
someInt = parseInt("not an integer") // This function returns nil if parsing fails
if someInt == nil {
print("That isn't a valid integer")
}