Sök…


Introduktion

"Ett valfritt värde innehåller antingen ett värde eller innehåller noll för att indikera att ett värde saknas"

Utdrag från: Apple Inc. "The Swift Programming Language (Swift 3.1 Edition)." iBooks. https://itun.es/us/k5SW7.l

Grundläggande valfria användningsfall inkluderar: för en konstant (låt), användning av valfritt i en slinga (om-låt), säkert avlägsna ett valfritt värde inom en metod (vakt-låt), och som en del av omkopplingsslingor (case-let) ), som har ett värde om noll, använder coalesce-operatören (??)

Syntax

  • var optionalName: optionalType? // förklara en valfri typ, som standard är noll
  • var optionalName: optionalType? = värde // förklara ett valfritt med ett värde
  • var valfritt Namn: optionalType! // förklara ett implicit oöppnat valfritt
  • valfri! // tvinga loss en valfri

Anmärkningar

Mer information om tillval finns i The Swift Programming Language .

Typer av optioner

Alternativ är en generisk enumtyp som fungerar som en omslag. Detta omslag tillåter en variabel att ha ett av två tillstånd: värdet på den användardefinierade typen eller nil , vilket representerar frånvaron av ett värde.

Denna förmåga är särskilt viktig i Swift eftersom ett av de angivna designmålen för språket är att arbeta bra med Apples ramverk. Många (de flesta) av Apples ramverk använder nil grund av dess användarvänlighet och betydelse för programmeringsmönster och API-design inom Objekt-C.

För Swift, för att en variabel ska ha ett nil , måste det vara ett valfritt. Alternativ kan skapas genom att lägga till antingen a ! eller en ? till variabeltypen. För att göra en Int valfri kan du till exempel använda

var numberOne: Int! = nil
var numberTwo: Int? = nil

? tillval måste vara uttryckligt oackade och bör användas om du inte är säker på om variabeln har ett värde eller inte när du kommer åt den. Till exempel, när du förvandlar en sträng till ett Int , är resultatet ett valfritt Int? , eftersom noll kommer att returneras om strängen inte är ett giltigt nummer

let str1 = "42"
let num1: Int? = Int(str1) // 42

let str2 = "Hello, World!"
let num2: Int? = Int(str2) // nil

! tillval tas automatiskt bort och bör endast användas när du är säker på att variabeln har ett värde när du kommer åt den. Till exempel en global UIButton! variabel som initieras i 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)
}

Ta bort ett valfritt

För att få tillgång till värdet på ett valfritt måste det tas upp.

Du kan villkorligt packa upp ett valfritt med valfri bindning och tvinga packa upp ett valfritt med ! operatör.

Villkorligt uppackning frågar effektivt "Har denna variabel ett värde?" medan kraftöppning säger "Denna variabel har ett värde!".

Om du tvingar bort en rad variabel som är nil , kommer ditt program att kasta ett oväntat hittat noll medan du tar bort ett valfritt undantag och kraschar, så du måste överväga noga om du använder ! är passande.

var text: String? = nil
var unwrapped: String = text! //crashes with "unexpectedly found nil while unwrapping an Optional value"

För säker uppackning kan du använda ett if-let uttalande, som inte kommer att kasta ett undantag eller krascha om det inslagna värdet är 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")
}

Eller ett vaktuttalande :

var number: Int?
guard let unwrappedNumber = number else {
    return
}
print("number: \(unwrappedNumber)")

Observera att omfånget för variabeln unwrappedNumber ligger i if-let uttalandet och utanför guard .

Du kan kedja bort urpakning av många tillval, detta är främst användbart i de fall din kod behöver mer än variabel för att fungera korrekt:

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.
}

Observera att alla variabler måste packas upp för att klara testet, annars skulle du inte ha något sätt att avgöra vilka variabler som har tagits upp och vilka inte.

Du kan kedja villkorade uttalanden med hjälp av dina tillval direkt efter att det har tagits upp. Detta betyder inget kapslat om - annat uttalande!

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!")
}

Nil Coalescing Operator

Du kan använda operatören noll sammanslagning för att packa upp ett värde om det är icke-noll, annars ger ett annat värde:

func fallbackIfNil(str: String?) -> String {
    return str ?? "Fallback String"
}
print(fallbackIfNil("Hi")) // Prints "Hi"
print(fallbackIfNil(nil)) // Prints "Fallback String"

Denna operatör kan kortsluta , vilket innebär att om den vänstra operanden är icke-noll, kommer den högra operanden inte att utvärderas:

func someExpensiveComputation() -> String { ... }

var foo : String? = "a string"
let str = foo ?? someExpensiveComputation()

I det här exemplet, eftersom foo är icke-noll, kommer en someExpensiveComputation() inte att kallas.

Du kan också kedja flera påståenden om noll sammandragning:

var foo : String?
var bar : String?

let baz = foo ?? bar ?? "fallback string"

I det här exemplet kommer baz att tilldelas det oöppnade värdet på foo om det är icke-noll, annars kommer det att tilldelas det oöppnade värdet på bar om det är icke-noll, annars tilldelas det fallback-värdet.

Valfri kedja

Du kan använda valfri kedja för att ringa en metod , få tillgång till en egenskap eller prenumerera på ett valfritt. Detta görs genom att placera en ? mellan den givna valfria variabeln och den givna medlemmen (metod, egenskap eller prenumeration).

struct Foo {
    func doSomething() {
        print("Hello World!")
    }
}

var foo : Foo? = Foo()

foo?.doSomething() // prints "Hello World!" as foo is non-nil

Om foo innehåller ett värde, kommer doSomething() att kallas på det. Om foo är nil , kommer inget dåligt att hända - koden misslyckas helt enkelt tyst och fortsätter att köras.

var foo : Foo? = nil

foo?.doSomething() // will not be called as foo is nil

(Detta är liknande beteende som att skicka meddelanden till nil i Objekt-C)

Anledningen till att valfri kedja namnges som sådan är för att "alternativ" kommer att spridas genom de medlemmar du ringer / åtkomst till. Vad detta betyder är att returnvärdena för alla medlemmar som används med valfri kedja kommer att vara valfria, oavsett om de skrivs som valfria eller inte.

struct Foo {
    var bar : Int
    func doSomething() { ... }
}

let foo : Foo? = Foo(bar: 5)
print(foo?.bar) // Optional(5)

Här foo?.bar returnerar en Int? även om bar är valfritt, eftersom foo sig är valfritt.

När alternativet sprids kommer metoder som returnerar Void att returnera Void? när anropas med valfri kedja. Detta kan vara användbart för att avgöra om metoden har kallats eller inte (och därför om det valfria har ett värde).

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")
}

Här jämför vi Void? returvärde med nil för att avgöra om metoden kallades (och därför om foo är icke-noll).

Översikt - Varför optioner?

Ofta vid programmering är det nödvändigt att göra en åtskillnad mellan en variabel som har ett värde och en som inte gör det. För referenstyper, som C-pekare, kan ett specialvärde som null användas för att indikera att variabeln inte har något värde. För inneboende typer, som ett heltal, är det svårare. Ett nominerat värde, som -1, kan användas, men det är beroende av tolkningen av värdet. Det eliminerar också det "speciella" värdet från normal användning.

För att hantera detta tillåter Swift alla variabler att deklareras som valfria. Detta indikeras av användningen av en? eller! efter typen (se typer av optioner )

Till exempel,

var possiblyInt: Int?

deklarerar en variabel som kanske inte innehåller ett heltal.

Specialvärdet nil indikerar att inget värde för tillfället tilldelas denna variabel.

possiblyInt = 5      // PossiblyInt is now 5
possiblyInt = nil    // PossiblyInt is now unassigned

nil kan också användas för att testa för ett tilldelat värde:

if possiblyInt != nil {
    print("possiblyInt has the value \(possiblyInt!)")
}

Notera användningen av ! i utskriften för att ta bort valfritt värde.

Som ett exempel på en vanlig användning av optioner, överväga en funktion som returnerar ett heltal från en sträng som innehåller siffror; Det är möjligt att strängen kan innehålla icke-siffriga tecken eller till och med vara tom.

Hur kan en funktion som returnerar ett enkelt Int indikera fel? Det kan inte göra det genom att returnera något specifikt värde, eftersom det skulle utesluta att värdet analyseras från strängen.

var someInt
someInt = parseInt("not an integer") // How would this function indicate failure?

I Swift kan den funktionen emellertid helt enkelt returnera en valfri Int. Sedan indikeras fel genom returvärde på 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")
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow