Swift基础语法 - 可选项

news2024/11/17 12:46:35

可选项(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"]) // 请输入用户名

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"]) // 请输入用户名

隐式解包(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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提升电脑运行速度,看这里就够了!

电脑是我们经常使用的工具之一&#xff0c;但是它却很容易出现问题&#xff0c;比如运行速度过慢&#xff0c;那么要如何提升电脑运行速度呢&#xff1f;方法1. 通过系统配置设置启动项1. 按下组合键“WinR”打开“运行”&#xff0c;在运行中输入“msconfig”然后按“回车”。…

LVGL-基于Windows系统Visual Studio模拟器搭建

LVGL-基于Windows系统Visual Studio模拟器搭建简述下载安装Visual Studio下载LVGL源码运行效果简述 LVGL是一个轻量级多功能图形库 丰富且强大的模块化图形组件&#xff1a;按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等高级的图形引擎&…

UUID简介以及java代码获取UUID示例

什么是UUIDUUID 是指&#xff08;UniversallyUnique Identifier&#xff09;通用唯一识别码&#xff0c;128位。RFC 4122描述了具体的规范实现。现实问题我们开发的时候&#xff0c;数据库表总会有一个主键&#xff0c;以前我们可能会使用自增的数字作为主键。这样做去确实查询…

PyTorch使用Visdom绘制训练过程曲线

最近在训练网络&#xff0c;网络的损失和准确率都是在终端输出的&#xff0c;很不直观&#xff0c;也看不出变化&#xff0c;就想着有没有一种工具可以实现实时的绘制模型的训练过程&#xff0c;然后就搜到了Visdom&#xff0c;发现这是个好东西啊&#xff0c;完全满足了我的需…

【Kafka】二.Kafka消息发布/消费流程

Kafka 通过对消费方进行分组管理来支持消息一写多读。 我画的图&#xff1a;工具&#xff08;processon在线画图&#xff09; 这个 Topic 分为 4 个 Partition&#xff0c;就是图中的 P1到 P4&#xff0c;上部的生产方根据规则选择一个 Partition 进行写入&#xff0c;默认规则…

算法练习-链表(一)

算法练习-链表&#xff08;一&#xff09; 文章目录算法练习-链表&#xff08;一&#xff09;解题技巧1. 实现链表1.1 节点的定义1.2 链表的遍历1.3 节点的查找1.4节点的插入1.4.1 链头插入1.4.2 链尾插入1.4.3 在给定节点之后插入1.5 删除节点1.5.1 删除给定节点之后的节点、1…

如何快速完成园区数据的可视化分析?

对于园区运营方来说&#xff0c;如果没有专业针对性的管理方案以及管理系统辅助的话&#xff0c;实现园区可视化管理的难度非常大&#xff0c;而且操作成本会很高。但如果园区运营方选择引进快鲸智慧楼宇推出的园区数据孪生可视化管理系统的话就会简单很多。 快鲸智慧楼宇数据孪…

python项目使用pipenv管理环境,如何使用pycharm调试模式

写在开始 了解pipenv的朋友们应该知道&#xff0c;使用pipenv管理项目环境后&#xff0c;仅pipenv虚拟环境中安装有项目的依赖包&#xff0c;测试机本身并没有安装这个依赖包&#xff0c;这就是pipenv使用的意义。但是&#xff0c;如果想要进入调试模式呢&#xff1f;我们要如…

Coqui TTS docker 使用记录

前言 之前介绍过 Coqui TTS 的安装&#xff0c;不过那个环境被我玩挂掉了…… 这次记录一下 docker 版本的使用。 参考网址&#xff1a;Docker images - TTS 0.11.1 documentation 正文 首先按照官网指示先把镜像 pull 下来。&#xff08;后记&#xff1a;确保 GPU driver…

重生之我是赏金猎人-番外篇-记一次层层突破的攻防演练

0x00 前言 本文简单记述了一下本人在某攻防演练过程中一次层层突破的有趣经历 技术性一般&#xff0c;但是层层突破属实艰难&#xff0c;并用到了比较多的思路&#xff0c;还望各位大佬多多指教 0x01 SSO账号获取 由于目标是某大学&#xff0c;对外开放的服务基本上都是一些…

CSS 预处理工具 Less 的介绍及使用 步骤

文章目录Less是什么Less的使用方法Less 中的注释Less 中的变量Less 中的嵌套Less 中的混合&#xff08;Mixin&#xff09;Less 中的运算Less 中的转译Less 中的作用域Less 中的导入Less实用实例文字超出省略文字垂直居中定位上下左右居中Less是什么 Less 是一门 CSS 预处理语言…

spring的事务控制

1.调用这个方法的对象是否是spring的代理对象&#xff08;$CGLIB结尾的&#xff09; 2.这个方法是否是加了Transactional注释 都符合才可以被事物控制 如果调用方法的对象没有被事物控制&#xff0c;那么被调用的方法即便是加了Transactional也是没用的 事务失效情况&#xf…

基于MATLAB计算MIMO信道容量(附完整代码与分析)

目录 一.介绍 二. 代码 三. 运行结果及分析 3.1 MIMO信道容量&#xff1a;固定发射天线数为4 3.2 MIMO信道容量&#xff1a;固定接收天线数为4 3.3 AWGN信道与瑞利信道容量 四. 总结 一.介绍 本文章将在MATLAB环境中分析MIMO信道容量&#xff0c;AWGN信道容量&#xf…

秒懂SpringBoot之全网最易懂的Spring Security教程

[版权申明] 非商业目的注明出处可自由转载 出自&#xff1a;shusheng007 文章目录概述简介原理默认实现使用Token认证方案JWT认证流程自定义Authentication Provider自定义Provider修改配置认证失败与授权失败处理认证失败处理授权失败处理支持方法级别的授权总结源码概述 现如…

PMP好考吗,有多大的价值?

关于PMP考试题型及考试内容&#xff0c;PMP考试共200道单选题&#xff0c;其中25道题不计分&#xff0c;会被随机抽查&#xff0c;答对106道题以上通过考试&#xff0c;参考比例106/175&#xff0c;60.57%估计答对&#xff08;10625&#xff09;道题及上即可通过&#xff0c;参…

全国进入裁员潮,到底是大厂难混?还是我技不如人?

前言 面对裁员&#xff0c;每个人的心态不同。他们有的完全没有料想到自己会被裁&#xff0c;有的却对裁员之事早有准备。大多数人&#xff0c;我想是焦虑失落的吧。 01 “降本增效”&#xff0c;HR怒提裁员刀 小默 | 32岁 芯片行业 人力资源 1月份&#xff0c;身处芯片行业H…

额度系统设计

一、额度生命周期额度生效/失效&#xff1a;授信的时候风控返回用户额度&#xff0c;当额度有效期到期之后额度失效&#xff1b;额度预扣/占用/释放&#xff1a; 当客户来提款的时候&#xff0c;只要提款金额小于授信额度(可用额度)时&#xff0c;先预扣&#xff0c;处理完系统…

如何让APP在Google Play中成为特色

Google Play覆盖了 190 多个地区&#xff0c;数十亿的用户&#xff0c;所以开发者都会希望APP在应用商店中获得推荐位。 Google Play 上的精选热门应用类型&#xff1a;热门游戏或应用&#xff0c;畅销应用&#xff0c;安装量增长的应用&#xff0c;产生最多收入的应用。 那么…

Pdfium.Net SDK 4.78.2704 完美Crack/Ptach

不限制时&#xff0c;/不限PDF体积、、、、、// version: 4.78.2704 | file size: 52.7 Mb Pdfium .Net SDK C# PDF 库 从头开始或从一堆扫描图像创建 PDF 编辑、合并、拆分和操作 PDF&#xff0c;提取文本和图像 嵌入独立的 Winforms 或 WPF PDF 查看器 支持&#xff1a;.Net…

软件性能测试方案怎么编写?权威的性能测试报告如何申请?

软件性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。性能测试在软件的质量保证中起着重要的作用&#xff0c;它包括的测试内容丰富多样。负载测试和压力测试都属于性能测试&#xff0c;两者可以结合进行。 一、软件性能测…