在可选类型之前,我们有个概念要搞清楚,类型安全。 什么是类型安全呢? 从字面上理解,就是这个类型是安全的,即这个类型不可以被赋予其他类型的值。 比如一个string类型的变量,不可以被赋值一个int值。
OC是不是类型安全呢? 不是的,比如很多对象都可以被赋予nil,这就属于赋予其他类型。
在OC中,如果想要判断某个值是否含有有效值,我们通常会使用nil来判断,但是nil的作用范围仅限于大部分对象,对于struct等类型,还需要判断是否NSNotFound等
基于此,Swift语法中进行了改良,提供了可选类型,可选类型更像是一个集合,表明这个类的实例属于{该类, nil} 中的一种。上述提到Swift是类型安全的语言,一个对象,要么是属于一个类,要么是属于nil,我们无法将nil赋值给一个Int类型的对象,但是可以将nil赋值给一个Optional Int对象
// swift/stdlib/public/core/Optional.swift
public enum Optional : ExpressibleByNilLiteral {
case none //要么是none
case some(Wrapped) //要么是某个类
public init(_ some: Wrapped)
public func map(_ transform: (Wrapped) throws -> U) rethrows -> U?
public func flatMap(_ transform: (Wrapped) throws -> U?) rethrows -> U?
public init(nilLiteral: ())
public var unsafelyUnwrapped: Wrapped { get }
}
nil赋值给可选类型
var code = 4
code = nil //error 'nil' cannot be assigned to type 'Int'
var code: Int? = 4
code = nil
另外要特别注意:在OC中,nil标志这个对象指向了一个不存在的对象,而在swift中,nil表明这个对象缺失有效的值。
我非常理解Swift为了兼容OC仍然使用了nil这个关键词,但是我觉得用JS中的Undefined会更通俗易懂。
强制解析(可选类型赋值给不可选类型)
在swift中,直接将可选类型赋值给非可选类型是会报错的。 如果我们确认可选类型有值,则可以强制解析来赋值,强制解析直接在可选类型的实例后面增加!即可
let string1: String? = "abc"
let string2: String = string1 //error Value of optional type 'String?' must be unwrapped to a value of type 'String'
let string1: String? = "abc"
let string2: String = string1! //correct
虽然第二种写法已经编译成功,但是因为这种做法可能会导致运行时崩溃,所以swift的官方文档还是推荐先进行判断再来赋值,即:
let string1: String? = "abc"
if string1 != nil { //best practice
let string2: String = string1!
print(string2)
}
可选绑定
在OC中,如果我们希望判断参数不为nil的时候,通常做法是这样的
if (a != nil && b != nil){
//case
}
而有了可选类型,swift中也带来了更优雅的写法
if let a1 = a, let b1 = b { // equal to (a != nil && b != nil)
}
另外在OC或者JS中判断某个值是否为空时,经常需要判断该类的上层是否有值,否则容易出现崩溃,如
if (person && person.homeInfo && person.homeInfo.adress){
}
我们在swift中可以使用可选链调用来解决
let adress = person?.homeInfo?.adress {
}
隐式解析可选类型
如果我们知道一个可选类型实际是有值的,那么一直判断nil然后再赋值的做法就有些冗余了,swift也带来了隐式解析,大白话讲就是: 虽然你声明成了一个可选类型,但是我知道你其实是有值的,所以我将你当成有值的类型来使用
举例:
//正常使用方法
let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // 需要感叹号来获取值
//隐式解析
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // 不需要感叹号
其他语法糖
在ES6中,提供了如下语法糖,如果对象是undefined,则使用其他默认值
let string = a || ‘string value’
而swift也参考了这种做法,不过符号变成了两个问号??
let a = string ?? "string value"
为什么swift设计了可选类型
- swift是类型安全的语言,需要可选类型来兼容oc并且提供一个缺失值的状态,类似于undefined
- 可选类型带来了判断nil的更强大和优雅的写法及语法糖
参考
https://swiftgg.gitbook.io/swift/swift-jiao-cheng/01_the_basics#optionals
转载:https://blog.csdn.net/njafei/article/details/116670935