2

Swift基础语法 - 可选项

 1 year ago
source link: https://blog.csdn.net/weixin_36162680/article/details/128718050
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

可选项(Optional)

  • 可选项,一般也叫可选类型,它允许将值设置为 nil
  • 在类型名称后面加个问号 ? 来定义一个可选项
var name: String? = "CSDN"
name = nil

var age: Int? //默认就是nil
age = 30
age = nil
在这里插入图片描述
var array = [2, 4, 6, 8]

func getNumber(_ index: Int) -> Int? {
    if index < 0 || index >= array.count {
        return nil
    }
    return array[index]
}

print(getNumber(1)) //Optional(4)
print(getNumber(-1)) //nil
print(getNumber(4)) //nil
在这里插入图片描述

强制解包(Forced Unwrapping)

  • 可选项是对其他类型的一层包装,可以将它理解为一个盒子
  • 如果为 nil ,那么它是个空盒子
  • 如果不为 nil ,那么盒子里装的是:被包装类型的数据
var age: Int? //默认就是nil
age = 10
age = nil
在这里插入图片描述
  • 如果要从可选项中取出被包装的数据(将盒子里装的东西取出来),需要使用 感叹号 ! 进行强制解包
var age: Int? = 20

let ageInt: Int = age!

print(ageInt) //20
在这里插入图片描述
  • 如果对值为 nil 的可选项(空盒子)进行强制解包,将会产生运行时错误
var age: Int?
age!
在这里插入图片描述

Fatal error: Unexpectedly found nil while unwrapping an Optional value

判断可选项是否包含值

let number = Int("123")

if number != nil {
    print("字符串转成数字成功为:\(number!)")
}else{
    print("字符串转成数字失败")
}
// 字符串转成数字成功为:123

可选项绑定(Optional Binding)

  • 可以使用 可选绑定 来判断可选项是否包含值
  • 如果包含就自动解包,把赋值给一个临时的常量( let )或者变量( var ),并返回 true ,否则返回 false
if let number = Int("123") {
    print("字符串转成数字成功为:\(number)")
    // number 是强制解包之后的Int值
    // number 作用域仅限于这个大括号
}else{
    print("字符串转成数字失败")
}
// 字符串转成数字成功为:123
enum Season : Int {
    case spring = 1, summer, autumn, winter
}

if let season = Season(rawValue: 8){
    switch season {
    case .spring:
        print("the season is spring")
    default:
        print("the season is other")
    }
} else {
    print("no such season")
}
// no such season
if let first = Int("5") {
    if let second = Int("45") {
        if first < second && second < 50 {
            print("\(first) < \(second) < 50")
        }
    }
}
// 5 < 45 < 50

if let first = Int("5"),
   let second = Int("45"),
   first < second && second < 50 {
    print("\(first) < \(second) < 50")
}
// 5 < 45 < 50

while 循环中使用可选项绑定

//遍历数组,将遇到 的正整数都加起来,如果遇到负数或者非数字,则停止遍历
var array = ["10", "20", "30", "ab", "-20", "40"]

var index = 0
var sum = 0
while let num = Int(array[index]), num > 0 {
    sum += num
    index += 1
}
print(sum)

空合并运算符 ?? (Nil - Coalescing Operator)

public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
  • a ?? b
  • a 是可选项
  • b 是可选项 或者 不是可选项
  • ba 的存储类型必须相同
  • 如果 a 不为 nil ,就返回 a
  • 如果 a 为 nil ,就返回 b
  • 如果 b 不是可选项,返回 a 时会自动解包
let a: Int? = 1
let b: Int? = 2
let c = a ?? b // c是Int? , Optional(1)
let a: Int? = nil
let b: Int? = 2
let c = a ?? b // c是Int? , Optional(2)
let a: Int? = nil
let b: Int? = nil
let c = a ?? b // c是Int? , nil
let a: Int? = 1
let b: Int = 2
let c = a ?? b // c是Int , 1
let a: Int? = nil
let b: Int = 2
let c = a ?? b // c是Int , 2
let a: Int? = nil
let b: Int = 2
//如果不使用 ?? 运算符
let c: Int
if let tmp = a {
    c = tmp
} else {
    c = b
}

多个 ?? 一起使用

let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 1
let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 2
let a: Int? = nil
let b: Int? = nil
let c = a ?? b ?? 3 // c是Int , 3

?? 跟 if let 配合使用

let a: Int? = nil
let b: Int? = 2
if let c = a ?? b {
    print(c)
}
//类似于 if a != nil || b != nil
let a: Int? = nil
let b: Int? = 2
if let c = a , let d = b {
    print(c)
    print(d)
}
// 类似于 if a != nil && b != nil

if 语句实现登录

func login(_ info: [String : String]) {
    let username: String
    if let tmp = info["username"] {
        username = tmp
    } else {
        print("请输入用户名")
        return
    }
    let password: String
    if let tmp = info["password"] {
        password = tmp
    } else {
        print("请输入密码")
        return
    }
    // if username ....
    // if password ....
    print("用户名:\(username)", "密码:\(password)", "登陆ing")
}
login(["username" : "jack", "password" : "123456"]) // 用户名:jack 密码:123456 登陆ing
login(["password" : "123456"]) // 请输入密码
login(["username" : "jack"]) // 请输入用户名
newCodeMoreBlack.png

guard 语句

guard 条件 else {
    // do something....
    退出当前作用域
    //return、break、continue、throw error
}
  • 当 guard 语句的条件为 false 时,就会执行大括号里面的代码
  • 当 guard 语句的条件为true时,就会跳过 guard 语句
  • guard 语句特别适合用来“提前退出”
  • 当使用 guard 语句进行可选项绑定时,绑定的常量( let )、变量( var )也能在外层作用域中使用
func login(_ info: [String : String]){
    guard let username = info["username"] else {
        print("请输入用户名")
        return
    }
    guard let password = info["password"] else {
        print("请输入密码")
        return
    }
    // if username ...
    // if password ...
    print("用户名:\(username)","密码:\(password)","登录ing")
}
login(["username" : "jack", "password" : "123456"]) // 用户名:jack 密码:123456 登陆ing
login(["password" : "123456"]) // 请输入密码
login(["username" : "jack"]) // 请输入用户名
newCodeMoreBlack.png

隐式解包(Implicitly Unwrapped Optional)

  • 在某些情况下,可选项一旦被设定值之后,就会一直拥有值
  • 在这种情况下,可以去掉检查,也不必每次访问的时候都进行解包,因为它能确定每次访问的时候都有值
  • 可以在类型后面加个感叹号 !定义一个隐式解包的可选项
let num1: Int! = 10
let num2: Int = num1
if num1 != nil {
    print(num1 + 6) // 16
}
if let num3 = num1 {
    print(num3) // 10
}
let num1: Int! = nil
//Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
let num2: Int = num1
在这里插入图片描述

字符串插值

  • 可选项在字符串插值或直接打印时,编译器会发出警告
var age: Int? = 10
print("My age is \(age)")
在这里插入图片描述
  • 至少有3种方法消除警告
print("My age is \(age!)")
//My age is 10

print("My age is \(String(describing: age))")
//My age is Optional(10)

print("My age is \(age ?? 0)")
//My age is 10

多重可选项

var num1: Int? = 10
var num2: Int?? = num1
var num3: Int?? = 10

print(num2 == num3) // true
  • 可以使用lldb指令 frame variable –R 或者 fr v –R 查看区别
var num1: Int? = nil
var num2: Int?? = num1
var num3: Int?? = nil

print(num2 == num3) // false

(num2 ?? 1) ?? 2 // 2
(num3 ?? 1) ?? 2 // 1

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK