2022年3月更新-可选类型
如果你有其他程序的开发经验,那么这一系列的swift入门教程分享,将很适合你。
开始吧,启动Xcode:打开Xcode,选择“Get started with a playground”,选择“macOS”下的“Blank”,在下一步里选定保存位置,就可以了。
常量和变量
let 声明常量
常量:是固定值,程序中不可改,声明时须赋值。
let π = 3.14
var 声明变量
变量:非固定值,程序中可改,未赋值不可用。
var a:String = "a string"
var b:Int = 10
var c:Float = 1.2
var d:Double = 1.9
var e:Bool = true
var f:Character = "a"//单个字符
变量未赋值不可以使用
var name:String
print(name)
//Variable 'name' used before being initialized
可以在一行中声明多个常量或者多个变量,用逗号隔开:
var x = 0.0, y = 0.0, z = 0.0
类型注解
上面示例代码中,在常量或者变量名后面加上一个冒号和空格,再加上类型名称,就是为声明的常量和变量加上了类型注解。
var welcomeMessage: String
如果你在声明常量或者变量的时候赋了一个初始值,Swift 可以推断出这个常量或者变量的类型,,没有给
welcomeMessage
赋初始值,所以变量welcomeMessage
的类型是通过一个类型注解指定的,而不是通过初始值推断的。
你可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型注解:
var red, green, blue: Double
注释
注释分单行、多行、多行嵌套
// 这是单行注释
/*
这是多行注释的第一行
这是多行注释的第二行
*/
/* 多行套用注释,外部
code
/* 多行套用注释,内部 */
code
多行套用注释,外部 */
输出语句
使用 print(_:separator:terminator:)
函数来输出当前常量或变量的值,
用字符串插值(string interpolation)
的方式把常量名或者变量名当做占位符加入到长字符串中
将常量或变量名放入圆括号中,并在开括号前使用反斜杠将其转义:
print(a,b,c)
//拼接字符串 只能拼接String类型的 在后面字符串的文章里还会再探讨;
print(a + h)
print("a + \(b)")
print("\(true) - \(100) - \(1.00)" + a)
关键字
请不要使用下列英文单词作为自已在Swift编程中的命名(包括但不仅限于下列单词)
- class,类
- deinit,析构函数
- enum,枚举
- extension,拓展类
- func,函数
- import,引入模块
- init,构造函数
- let,常量
- protocol,协议
- static,静态
- struct,结构体
- subscript,下标语法
- typealias,类型别名
- var 变量
数据类型
- 整型
- 浮点型
- 布尔
- 字符
- 字符串 这里就不展开各个类型来说了,主要探讨swift的类型安全和类型推断。
类型推断
Swift 是一个类型安全(type safe) 的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks) ,并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
类型推断其实很简单,对于声明的常量或者变量,如果没有显式的指定类型(就是上面说到的类型注解),那么编译器在编辑代码的时候,只要检查你赋给变量或者常量的值,就可以推断出对应的类型。
var h = "this is a string"
//输出数据类型
print(type(of: h))
let anotherPi = 3 + 0.14159
// anotherPi 会被推测为 Double 类型
类型别名
typealias dog = Int//dog就是Int
var aa:dog = 10
var bb:Int = 20
print(aa,bb)
typealias S = String
var cc:S = "WAL"
类型转换
SomeType(ofInitialValue)
是调用 Swift 构造器并传入一个初始值的默认方法,用来做强制的类型转换。
var dd = 10
print("this is a " + String(dd));
print("this is a " + String(false));
var ee = "hello"
print(Int(ee)) //nil
var ff = "100"
print(Int(ff)) //Optional(100)
var gg = Double(aa) ?? 0
print(Int(110.5))//110
print(Double(10))//10.0
print(Bool(100))//true
可选类型optional
什么是可选类型呢,这个概念在C 和 Objective-C 中并没有,用来处理值可能缺失的情况,我们可以通过在类型后面加一个 ?
来将变量声明为 Optional 的。用一个例子来说:
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber 被推测为类型 "Int?", 或者类型 "optional Int"
这里使用了Int
类型的构造器,将一个 String
值转换成一个 Int
值,但并不是所有的字符串都可以转换成一个整数,构造器可能会失败,所以返回了一个可选类型Int?
,而不是Int
。这样就可以理解可选类型的意义了吧。
var aaa:Int? = nil
print((aaa) ?? 10)
可以给可选变量赋值为nil
来表示他没有值,或者声明一个可选变量或者常量并且没有赋值,他们会自动被设置成nil
。Swift 里的 nil 和 objc 里的 nil 完全不是一回事儿。objc 的 nil 是一个实实在在的指针,它指向一个空的对象;在 Swift 中,nil
不是指针,它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为 nil
,不只是对象类型。
var bbb:Int? = 100
print(bbb)//Optional(100)
//确定有真实的值 可以用叹号语法解析出真实的值
print(bbb!)//100
var value:String? = "hello"
print(value)
if value == nil {
print("no value")
} else {
//拼接的时候也要先解析出真实值
print("value is" + value! + String(bbb!))
}
当确定可选类型包含真实值之后,可以通过叹号语法来获取值,这就是可选值的强制解析(forced unwrapping)。使用 !
来获取一个不存在的可选值会导致运行时错误。
可选绑定
使用可选绑定(optional binding) 来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。在 if
条件语句中使用常量和变量来创建一个可选绑定,仅在 if
语句的句中(body
)中才能获取到值。相反,在 guard
语句中使用常量和变量来创建一个可选绑定,仅在 guard
语句外且在语句后才能获取到值。
var f:Int? = 10
//这里最好用 let var 会报警告
if let fValue = f {
//这里就不需要 用叹号运算符 解析真实值了
print("fvalue = \(fValue)")
}
var obj1:Int? = 1
var obj2:Int? = 2
//if-let语法结构来进行optional类型值的绑定操作
if let tmp1 = obj1, let tmp2 = obj2, tmp1 < tmp2 {
print(tmp1, tmp2)
}
隐式解析可选类型
在确定了可选类型有值之后,后面每次使用都要判断和解析可选值,效率就非常低了,所以我们可以声明的时候,把可选的类型的后面的问号(String?
)改成感叹号(String!
)来声明一个隐式解析可选类型。
一个隐式解析可选类型其实就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都使用解析来获取可选值。
var g:Int! = 100
print(g)//不需要感叹号强制解析
模拟面试
一、简述在swift中,对符号"?" 和 "!" 的理解
回答要点:
- 首先分类型和实例两个方面理解,"?"出现在类型后表示optional类型,出现在实例后表示可选链调用。"!" 出现在类型后表示默认隐式解析,出现在实例后表示强制拆包。
- 这两个符号都和swift中的optional类型相关,optional类型是swift语言强调安全性的一种方式,某个变量可否为空,应该是逻辑上决定的,而不是不可预知不可控的
- if-let结构与optional类型值的结合使用,可以编写出优化安全的代码
元组
元组是不同数据类型的集合,可通过下标或关键字获取元素。
申明元组
var a1 = (1,15,6.0,"hello")
print(a1)
//指定元组中的类型
var b1:(Int,String) = (10,"swift")
print(b1)
//空元组
var c1 = ()
//元组取值
print(a1.3)//hello
//赋值 值传递 copy一份
var d1 = ("hello",true)
var e1 = d1
d1.0 = "val"
var f1 = (name1:"hello",name2:true)
print(f1.name1)
var g1:(name1:Int,name2:String) = (100,"hello")
print(g1.name1)
拆分元组
let (n1,n2) = ("swift",2.0)
print(n1)
let (_,_,n3) = ("swift",2.0,true)
print(n3)
传递元组
//元组可以作为参数 和 返回值 函数多返回值
var data = (1,"hello",true)
func handle(param:(Int,String,Bool))->(Int,String,Bool) {
var data_param = param
data_param.0 = 300
data_param.1 = param.1 + " lily"
data_param.2 = false
return data_param
}
let resut = handle(param: data)
print(resut)