「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。
- 本文主要介绍swift中的
Optional可选值
1. 认识Optional
我们开发中经常使用?代表就是Optional,表示可以为空。
class Person {
var name:String?
}
let p = Person()
print(p.name as Any)
打印结果为nil,我们也可以使用Optional< T >表示
class Person {
var name:Optional<String> = nil
}
let p = Person()
print(p.name as Any)
var name:String? 等同于 var name:Optional<String> = nil
- 我们查看原码
Optional.swift
它是一个枚举,可以表示为空。我们自己定义一个Optional
enum MyOptional<Value>{
case none
case some(Value)
}
func getOddValue(_ value:Int) -> MyOptional<Int> {
if value%2 == 0 {
return .some(value)
}else{
return .none
}
}
//定义一个数组
var array = [1,2,3,4,5,6]
for element in array{
let oddValue = getOddValue(element)
array.remove(at: array.firstIndex(of: oddValue))
}
这个时候编译器就会检查我们当前的 value 会发现他的类型和系统编译器期望的类型不符,这 个时候我们就能使用 MyOptional 来限制语法的安全性。
for element in array{
let oddValue = getOddValue(element)
switch oddValue {
case .some(let value):
array.remove(at: array.firstIndex(of: value)!)
case .none:
print("\(element) vlaue not exist")
}
}
我们通过枚举的匹配模式取出对应的值,达到类型一致,我们也可以把我们自定义的Optional换成Int?达到一样的效果。
这样我们其实是利用当前编译器的类型检查来达到语法书写层面的安全性。
2. 可选值的绑定
上面的使用的匹配模式进行判断,但是如果比较多的话比较繁琐,我们可以这样
for element in array{
let oddValue = getOddValue(element)
if let value = oddValue {
array.remove(at: array.firstIndex(of: value)!)
}
}
用 if let 的方式来进行可选值绑定,当然我们在开发中也会经常使用守卫模式guard let
比如上面的列子中我们只想移除偶数2,就会嵌套逻辑的判断
我们使用guard 就可以直接进行判断,方便我们处理逻辑。
3. 解包
- 强制解包
我们知道我们的
opyional是一个?可选值,它可能有值,可能没有。我们使用!表示强制解包,代表我们确定它一定有值。
但是我们对于一个
可能没值的可选值进行强制解包则会报错
- 隐式解包
隐式解析可选类型是可选类型的一种,使用的过程中和
非可选类型无异。它们之间唯一 的区别是,隐式解析可选类型是你告诉对Swift 编译器,我在运行时访问时,值不会 为 nil。
我们使用可选值的时候,!修饰的变量告诉编译器我们这个肯定有值不需要在进行解包了
我们使用xib的时候会默认解包告诉编译器,这个变量肯定存在
4. 空合并运算符
空合并运算符以 ?? 的形式来表达,它本质上是一个函数,其函数的定义如下:
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 进行空判断,如果 a 包含一个值就进行解包,否则就返回 一个默认值 b
- 表达式 a 必须是
Optional类型 - 默认值 b 的类型必须要和 a 存储值的
类型保持一致
a存在的话就是a类型的值是可选值类型
a不存在的话就是b类型的值
a 必须是
可选值才可以解包判断
5. 可选链
可选链表示我们可以在这个链上可以使用点语法或者下标进行访问,当我们对象是可选的则表示通过链进行访问的的对象,属性,或者方法可以为空。看个列子
当我们对一个定义ottional的属性或者对象调用它的方法时会进行判断是否存在,不存在的方法直接直接返回,相当于在oc中给一个nil对象发送消息,消息的接受者为nil直接返回什么也不做。而访问属性的时候相当于解包返回nil.
可选连
对于可选值类型的操作结果依然是可选值,可选链对于下标和函数调用也适用
所以swift的可选值的使用是一种安全的体现,是我们的程序更加健壮。
6. 元类型、AnyClass、Self
我们开发中因为swift是一种安全语言我们经常会要转换类型下面进行区分
- Any: 代表
任意类型,包括funcation类型或者optional类型(类似oc 中id) - AnyClass 代表
任意实例的类型(类似oc中class) - AnyObject: 代表任意类的
instance, 类的类型,仅类遵守的协议(类似oc中NSObject的实例,转换某一个实例对象) - T.self: 如果 T 是实例对象,返回的就是
它本身,T 是类,那么返回的是Metadata(类似oc中的isMemberOf,指向isa) - T.Type: 一种类型,
T.self是T.Type类型 - type(of:): 用来获取一个值的
动态类型
- Self和self的区别:
protocol Copyable {
func copy() -> Self
func clamp(intervalToClamp: Self) -> Self
}
Self来说它只是表示特定类型,并且只能用在协议中或者作为某个类的方法的返回值类型,而self在实例方法中代指当前实例,在类方法中则代指当前类。
7. as , as?和 as!
- as:把当前类型转换为
其他类型
- as?把当前类型转换为
可选类型
- as!把当前类型
强制转换为其他类型,不同的话会造成崩溃
只有在明确相同类型的情况下使用as!否则使用as?
8. 总结
- 可选值
Optional本质是一个枚举,可能为none。可选值解包使用!表示,但是一旦为空,就会崩溃。我们通常会对可选值进行绑定判断,使用if let判断,我们也可以使用gurad let进行return。 - 可选值我们可以使用
??进行判断,一般设置一些默认值 - 对于
Optional的对象我们可以使用点语法或者下标进行可选链的调用,对于这个链上某一个可选值为空的话,也不会报错,相当于消息接受者为空,直接返回。 - 类型范围
Any>AnyClass>AnyObject,T.self以及T.type根据实际选则。 - 如果
明确类型的话可以强制转换,否则使用as?可选类型。