Swift 可选类型使用及设计思路推测, ?、!、 ??等的用法
在可选类型之前,我们有个概念要搞清楚,类型安全。 什么是类型安全呢? 从字面上理解,就是这个类型是安全的,即这个类型不可以被赋予其他类型的值。 比如一个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中,提供了
20000
如下语法糖,如果对象是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
- Swift类型推测在可选调用中的小提示
- Swift教程之可选类型【问号的用法】
- Swift中的可选类型(Optional)以及?和!的用法详解
- Swift类型推测在可选调用中的小提示
- Swift类型推测在可选调用中的小提示
- [swift]-可选类型使用
- Swift中使用可选类型完美解决占位问题
- Swift学习记录 -- 10.可选类型的使用
- swift中的可选类型Optional?、解包!和隐式解包的可选类型的用法
- Swift可选类型的使用
- Swift可选类型在函数中的使用
- swift 可选类型使用场景示例
- [Sql Server2008]使用SQL Server 2008中的hierarchyid类型来设计具有树型层次关系的表(转)
- 读懂Swift 2.0中字符串设计思路的改变
- nmap软件使用思路及常见用法
- Swift-Optional(可选类型?!)
- 窥探Swift之新添数据类型元组与可选值
- [设计模式]在CodeDom代码生成中使用Decorator模式实现类型创建
- Hibernate Annotation关系映射的几种类型映射用法及使用方法
- 使用Swift操作NSDate类型基础