(Optional)

  • Optional, also commonly called optional types, allows values to be set to nil
  • Add a after the type nameThe question mark?To define an optional
var name: String = "Jack"
name = nil

var age: Int?
age = 10
age = nil
Copy the code

In C, when you declare a variable, it’s automatically given an initial value, which Swift doesn’t do, but Swift’s Optional has a default initial value nil

func test(a) {
    var age: Int -->There is no initial value and must be assigned before it can be usedvar weight: Double?  -->The default initial value isnil, equivalent to thevar weight: Double? = nil
}
Copy the code

Use scenarios where you might need to use nil

var array = [1.13.45.33]
func get(_ index: Int) -> Int? {
    if index < 0 || index > = array.count {
        return nil
    }
    return array[index]
}
print(get(1))// Optional(15)
print(get(-1))// nil
print(get(5)) // nil
Copy the code


Forced Unwrapping

  • The alternative is a layer of packaging for other types, which can be thought of as a box
    1. If it isnilSo it’s an empty box
    2. If not fornilThe box contains the type of data to be wrapped
var age: Int? // Default is nil
age = 10
age = nil
Copy the code

  • If you want to retrieve wrapped data from the options (take out the contents of the box), use thisExclamation point!Forced unpack
var speed: Int? = 10
var speedInt: Int = speed!
speedInt + = 10
Copy the code
  • If the pair of values is zeronilAn optional (empty box) for forced unpacking will generate a runtime error
var age: Int?
age!Operation error:Fatal error: Unexpectedly found nil while unwrapping an Optional value: file Optional.xcplaygroundpage
Copy the code


Determines whether the optional option contains a value

let number = Int("123")
if number ! = nil {
    print("String conversion to integer successful:\(number!)")}else {
    print("String conversion to integer failed")}Copy the code


Optional Binding

  • You can useOptional bindingTo determine whether the option contains a value

If it does, it is automatically unpacked, assigns the value to a temporary constant (let) or variable (var), and returns true, otherwise returns false

if let number = Int("123") {
    print("String conversion to integer successful:\(number)")
    -->Number is after forced unpackingThe Int value
    -->Number is only used for this curly bracket}else {
    print("String conversion to integer failed")}Copy the code

Used in enumerated values

enum Season: Int {
    case spring = 1, summer, autumn, winter
}
if let season = Season(rawValue: 6) {  -->It's possible to get the correspondingcaseIf you can't get it, then the result is nullswitch season {
    case .spring:
        print("the season is spring")
    default:
        print("the season is other")}}else {
       print("no such season")}Copy the code

Note the following equivalents

if let first = Int("4") {
    if let second = Int("42") {
        if first < second && second < 100 {
            print("\(first) < \(second)"100")}}}= = = = = =The equivalent is as follows, with optional bindings separated by commasifJudge conditionsif let first = Int("4"),
    let second = Int("42"),
    first < second && second < 100 {
    print("\(first) < \(second)"100")}Copy the code


Optional bindings are used in the while loop

---->Iterate through the number group, adding up all the integers encountered in the drawing. If you encounter a negative number or non-number, stop the conveniencevar strs = ["10"."20"."abc"."To 30"."30"]
var index = 0
var sum = 0
while let num = Int(strs[index]), num > 0 {
    sum + = num
    index + = 1
}
print(sum) / / 30
Copy the code

Null merge operator?? (Nil – Coalescing Operator)

public func ?? <T> (optional: T? .defaultValue: @autoclosure(a)throws -> T?). rethrows -> T?
public func ?? <T> (optional: T? .defaultValue: @autoclosure(a)throws -> T) rethrows -> T
Copy the code

a ?? b

  • aMust beIs optional
  • bIt is optional or not optional
  • bwithaThe storage types must be the same
  • ifaDon’t fornil, return a
  • ifafornil, return b
  • ifbNot optional, returnaWhen the packet is automatically unpacked
let a: Int? = 1
let b: Int? = 2
let c = a ?? b / / c Int? , Optional(1)

Copy the code
let a: Int? = nil
let b: Int? = 2
let c = a ?? b / / c Int? , Optional(2)
Copy the code
let a: Int? = nil
let b: Int? = nil
let c = a ?? b / / c Int? , nil
Copy the code
let a: Int? = 1
let b: Int = 2
let c = a ?? b / / c Int, 1
Copy the code
let a: Int? = nil
let b: Int = 2
let c = a ?? b / / c Int, 2
Copy the code

If not?? Some of the code is more difficult to write

let a: Int? = nil
let b: Int = 2
let c: Int
if let tmp = a {
    c = tmp
} else {
    c = b
}
Copy the code


More than one?? Used together

Let’s do it from left to right

let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3 //c is Int, 1
Copy the code
let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3 //c is Int, 1
Copy the code
let a: Int? = nil
let b: Int? = nil
let c = a ?? b ?? 3 //c is Int, 1
Copy the code


?? Use with if let

let a: Int? = nil
let b: Int? = 2
if let c = a ?? b {
    print(c)
}
-->Similar to theif a ! = nil || b ! = nil {}
Copy the code
if let c = a, let d = b {
    print(c)
    print(d)
}
-->Similar to theif a ! = nil && b ! = nil {}
Copy the code


The if statement implements the login

func login(_ info: [String : String]) {
    let username: String
    if let tmp = info["username"] {
        username = tmp
    } else {
        print("Please enter user name")
        return
    }

    let password: String
    if let tmp = info["password"] {
        password = tmp
    } else {
        print("Please enter your password")
        return
    }

    print("User name:\(username)"."Password:\(password)".Login "ing")
}

login(["username": "jack"."password": "123456"])
login(["password": "123456"])
login(["username": "jack"])
* * * * * * * * * * * *Running result Username: Jack Password:123456Login ing please enter user name please enter passwordCopy the code


Guard statement

The above login service is implemented through Guard

func login(_ info: [String : String]) {
    guard let username = info["username"] else {
        print("Please enter user name")
        return
    }

    guard let password = info["password"] else {
        print("Please enter your password")
        return
    }

    print("User name:\(username)"."Password:\(password)".Login "ing")
}

login(["username": "jack"."password": "123456"])
login(["password": "123456"])
login(["username": "jack"])
* * * * * * * * * * *Running result Username: Jack Password:123456Login ing please enter user name please enter passwordCopy the code


Implicitly Unwrapped Optional

  • In some cases, an option will always have a value once it has been set
  • In this case, you can remove the checking, and you don’t have to unpack it every time you access it, because it makes sure it has a value every time you access it
  • You can add one after the typeExclamation point!Defines an implicit unpacking option
let num1: Int! = 10 // If you are certain that a variable will never be nil, you can use this declaration,
let num2: Int = num1 // Num1 is optional. Num1 can be unpacked automatically
if num1 ! = nil {
    print(num1 + 6)}if let num3 = num1 {
    print(num3)
}


Copy the code

If you assign nil to an optional variable of implicit unpack type, a runtime error will occur when that variable is assigned to another variable/constant

let num4: Int! = nil
let num5: Int = num4  -->Num4, num4, num4, num4, num4, num4, num4nil, so thenilAssign to num5:IntNum5 cannot be nullFatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
Copy the code

The above case, let a person feel the use of the belt! “Optional” has many risks. In fact, it is safer to use the following way.

var num5: Int = 10
let num5: int = num56
Copy the code

So you can see the errors, if any, at least before the program runs.

In fact, in most scenarios, we also recommend using tape? That’s optional! What is the point of declaring optional?

  • If you provide a set of apis for the outside world to use, and expect users to strictly comply with your requirements, do not passnilYou can use this if you expect the application to crash when the user misuses it. Other than that, it’s better not to.


String interpolation

Optional The compiler will warn if the string is interpolated or printed directly

var age: Int? = 10
print("My age is \(age)")// String interpolation directly generates a compiler warning
//️String Interpolation a debug description for an optional value; did you mean to make this explicit? ️
Copy the code

There are three common ways to eliminate warnings

var age: Int? = 10
print("My age is \(age!)")
print("My age is \(String(describing: age))")
print("My age is \(age ?? 0)")
Copy the code


Multiple options

var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10
print(num2 = = num3) // true
Copy the code

num1,num2,num3The structures of are as follows

Look at the following

var num1: Int? = nil
var num2: Int?? = num1
var num3: Int?? = nil
print(num2 = = num3) // false

(num2 ?? 1) ?? 2  / / 1
(num1 ?? 1) ?? 2  / / 2
Copy the code

You can use the LLDB directive frame variable-r or fr V-r to view the internal information of a variable.

So much for the Swift options.