数据类型的关键字
T
Any
AnyClass
AnyObject
T
表示泛型,可以指代任何数据类型Any
表示任何数据类型AnyClass
表示 class 类型AnyObject
表示 class 类型的实例
数据类型的分类
在 Swift 中数据类型分为值类型和引用类型,只有类是引用类型。其他类型都是值类型,包括整型、浮点型、布尔型、字符型、字符串、元组、数组、字典、集合、枚举等类型本质上都是结构体类型,它们均属于值类型。
如 Swift 中 String 是值类型、NSString 是引用类型。
值类型是在赋值或给函数传递参数时创建一个副本,把副本传递过去,在函数的调用过程中不会影响原始值。
引用类型是在赋值或给函数传递参数时把本身引用传递过去,在函数调用过程中会影响原始数据。
值类型参数不能直接以引用类型传递,如果想要在函数内改变值类型参数的原始值,需要将值类型参数声明为 inout,在使用实例前加上 & 符号。
数据类型的获取
Swift 是一个强类型语言,而强类型语言相对于弱类型语言的一个优点是更加严谨。我们可以通过类型来判断出,实例有哪些特征。
type(of: T)
获取值的类型
var name = "huangjian"
print(type(of: name)) // String
is
检查值的类型
var msg = "Hello"
print(msg is String, msg is Int) // true false
数据类型的转换
as
给值做类型转换(父子类关系)as?
给值做向下可选类型转换as!
给值做向下强制类型转换
类型强转
if Int("huangjian") != nil {
print(Int("huangjian")!)
}
if let value = Int("huangjian") {
print(value)
}
备注:[Substring]
可选类型
可选类型 Optional<T>
表示变量可能为 T
类型的值,也可能为 nil
值。
为什么会有可选类型这种设计?历史渊源
int age // 未赋初值,值为 0
bool success // 未赋初值,值为 false
创建字符串的可选类型
let name: String? = "huangjian"
let name: Optional<String> = "huangjian"
可选类型变量的强制解析,在可选类型变量后面加上感叹号 !
即可
print(name) // Optional("huangjian")
print(name!) // huangjian
使用操作符 !
去获取值为 nil
的可选变量会有运行时错误,这时需要进行判断,或者赋值给一个临时常量
if name != nil {
print(name!)
}
if let your_name = name {
print(your_name)
}
可选类型的常量,可以在声明后,进行一次初始化赋值
let name: String
name = "huangjian"
let name: String?
name = "huangjian"
备注:还有一种叫自动解析的语法,比如 let name: String! = ""
,但解析与上毫无差别,所以不推荐
可选类型的使用
如果直接获取可选类型的变量,比如 print(name)
,会有 Xcode 警告,它会建议我们使用下面三种方式处理:
Expression implicitly coerced from ‘String?’ to ‘Any’:
- Provide a default value to avoid this warning 设置默认值
- Force-unwrap the value to avoid this warning 强制解析
- Explicitly cast to ‘Any’ with ‘as Any’ to silence this warning 转换成 Any 类型的变量
有值测试:
let name: String? = "huangjian"
print(name ?? "DefaultName") // [output]: huangjian
print(name!) // [output]: huangjian
print(name as Any) // [output]: Optional("huangjian")
if name != nil {
print(name!) // [output]: huangjian
}
if let your_name = name {
print(your_name) // [output]: huangjian
}
无值测试:
let name: String? = nil
print(name ?? "DefaultName") // [output]: DefaultName
// print(name!) // 运行崩溃
print(name as Any) // [output]: nil
if name != nil {
print(name!) // 不执行
}
if let your_name = name {
print(your_name) // 不执行
}
可选链
可选链(Optional Chaining)是一种可以请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为 nil。
可选链返回两个值:
- 如果目标有值,调用就会成功,返回该值
- 如果目标为 nil,调用将返回 nil
多次请求或调用可以被链接成一个链,如果任意一个节点为 nil 将导致整条链失效。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
func printNumberOfRooms() {}
}
let john = Person()
let roomCount = john.residence!.numberOfRooms
// Fatal error: Unexpectedly found nil while unwrapping an Optional value
let john = Person()
/**
链接可选 residence? 属性,
如果 residence 存在则取回 numberOfRooms 的值
*/
if let roomCount = john.residence?.numberOfRooms {
print("John's room count is \(roomCount)")
} else {
print("不能查看") // 执行此句
}
let john = Person()
/**
你可以使用可选链的来调用可选值的方法并检查方法调用是否成功
即使这个方法没有返回值,你依然可以使用可选链来达成这一目的
*/
if john.residence?.printNumberOfRooms() != nil {
print("可以输出")
} else {
print("无法输出") // 执行此句
}
Optional 与 Any 的关系
nil 不是一种类型
Any 类型的变量不能与 nil 值进行相等判断,只有 Optional 类型的变量才能与 nil 值进行相等判断
错误做法:
let name: String? = nil
let value: Any = name as Any
///! Comparing non-optional value of type 'Any' to 'nil' always returns false
if value == nil {
print("value is nil.")
} else {
print("value is Not nil.") // run here.
}
type(of: value) == Optional<String>.self // true
正确做法:将 Any 改成 Any?
let name: String? = nil
let value: Any? = name
if value == nil {
print("value is nil.")
} else {
print("value is Not nil.")
}