swift 可选值


// 可选值

let cities_ = ["Paris": 2241, "Madrid": 3165, "Amsterdam": 827, "Berlin": 3562]

//  madridPopulation 的类型是可选类型 Int?,而非 Int。一个 Int? 类型的值是 Int 或者特

//殊的 “缺失” 值 nil

let madridPopulation: Int? = cities_["Madrid"]

// 检验查询是否成功

// 写 madridPopulation! 是为了 获取可选值中实际的 Int 值。后缀运算符 ! 强制将一个可选类型转换为一个不可选类型

if (madridPopulation != nil) {

print("The population of Madrid is \(madridPopulation! * 1000)")

} else {

print("Unknown city: Madrid")

}

if let madridPopulation = cities_["Madrid"] {

print("The population of Madrid is \(madridPopulation * 1000)")

} else {

print("Unknown city: Madrid")

}

/**

如果 optional 变量是非 nil 的话,我们真的不愿意对 defaultValue 进行求值 ——

因为这可能是一个开销非常大的计算,只有绝对必要时我们才会想运行这段代码

*/

/**

Swift 还给 ! 运算符提供了一个更安全的替代,?? 运算符。使用这个运算符时,需要额外提供 一个默认值,当运算符被运用于 nil 时,这个默认值将被作为返回值

?? 运算符会检验它的可选参数是否为 nil。如果是,返回 defaultValue 参数;否则,返回可选 值中实际的值

*/

//infix operator ??

func ??<T>(optional: T?, defaultValue: T) -> T {

if let x = optional {

return x

} else {

return defaultValue

}

}

/**

上面的定义有一个问题:如果 default 的值是通过某个函数或者表达式得到的,那么无论可选 值是否为 nil,defaultValue 都会被求值。

通常我们并不希望这种情况发生:一个 if-then-else 语句应该根据各分支关联的值是否为真,只执行其中一个分支。同样的道理,?? 运算符应该只 在可选值参数是 nil 时才对 defaultValue 参数进行求值。举个例子,假设我们像下面这样调用 ??:

作为 T 类型的替代,我们提供一个 () -> T 类型的默认值。现在 defaultValue 闭包中的代码仅 当我们对它进行调用时才会执行。在这样的定义下,代码会如预期一样,只在 else 分支中被执 行。美中不足的是,当调用 ?? 运算符时需要为默认值创建一个显式闭包。例如,我们需要编写 以下代码:

myOptional ?? { myDefaultValue }

*/

func ??<T>(optional: T?, defaultValue: () -> T) -> T {

if let x = optional {

return x

}

else {

return defaultValue()

}

}

//Swift 的 autoclosure 类型标签来避开创建显式闭包的需求。

//它会在所需要的闭包中隐式地将参数封装到 ?? 运算符。这样一来,我们能够提供与最初相同的 接口,但是用戶无需再显式地创建闭包封装 defaultValue 参数。Swift 标准库中使用的实际定 义如下:

//?? 运算符提供了一个相较于强制可选解包更安全的替代,并且不像可选绑定一样繁琐

infix  operator ?? { associativity right precedence 110 }

func ??<T>(optional: T?, @autoclosure defaultValue: () -> T) -> T {

if let x = optional {

return x

} else {

return defaultValue()

}

}

// 玩转可选值

// 可选值链

// 可选链,它用于在被嵌套的类或结构体中对方法或属性进行选择

struct Order {

let orderNumber: Int

let person: Person?

}

struct Person {

let name: String

let address: Address?

}

struct Address {

let streetName: String

let city: String

let state: String?

}

// 给定一个 Order,如何才能查找到客戶的状态呢?我们可以使用显式解包运算符:

// order.person!.address!.state! 如果任意中间数据缺失,这么做可能会导致运行时异常。使用可选绑定相对更安全

/**

if let myPerson = order.person {

if let myAddress = myPerson.address {

if let myState = myAddress.state { // ...

但这未免有些烦琐。若使用可选链,这个例子将会变成:

*/

var address = Address(streetName: "guangzhou",city: "huangpu",state: "wengcong")

var person = Person(name: "RHC",address:address)

var order = Order(orderNumber: 8,person:person)

// 使用问号运算符来尝试对可选类型进行解包,而不是强制将它们解包。当任意一个组成项 失败时,整条语句链将返回 nil

if let myState = order.person?.address?.state {

print("This order will be shipped to \(myState)")

} else {

print("Unknown person, address, or state.")

}

// 分支上的可选值

//if let可选绑定机制,但是Swift还有其他两种分支语句,switch和 guard,它们也非常适合与可选值搭配使用

/**

*  我们简单地为 case 分支中的每个模式添加一个 ? 后 缀。如果我们对一个特定值没有兴趣,也可以直接匹配 Optional 的 None 值或 Some 值

*/

switch madridPopulation {

case 0?: print("Nobody in Madrid")

case (1..<1000)?: print("Less than a million in Madrid")

case .Some(let x): print("\(x) people in Madrid")

case .None: print("We don‘t know about Madrid")

}

/**

guard 语句的设计旨在当一些条件不满足时,可以尽早退出当前作用域。没有值存在时就提早退出,是一个很常?的使用情境。将它和可选绑定组合在一起可以很好地处理 None 的情况。 很显然,guard 语句后面的任何代码都需要值存在才会被执行。举个例子,我们可以重写打印 给定城市居?数量的代码

*/

func populationDescriptionForCity(city: String) -> String? { guard let population = cities_[city] else { return nil }

return "The population of Madrid is \(population * 1000)"

}

populationDescriptionForCity("Madrid")

// 可选映射

/**

? 运算符允许我们选择性地访问可选值的方法或字段。然而,在很多其它例子中,若可选值存 在,你可能会想操作它,否则返回 nil

*/

func incrementOptional(optional: Int?) -> Int? {

guard let x = optional else { return nil }

return x + 1

}

// MARK: - 将 incrementOptional 函数和 ? 运算符一般化,然后为可选值定义一个 map 函数。这 样一来,我们不仅能像 incrementOptional 那样,对一个 Int? 类型的值做增量运算,还可以将 想要执行的任何运算作为参数传递给 map 函数

// map 函数接受一个类型为 Wrapped -> U 的 transform 函数作为参数。如果可选值不是 nil, map 将会将其作为参数来调用 transform,并返回结果;否则 map 函数将返回 nil。这个 map 函数是 Swift 标准库的一部分

extension Optional {

func map<U>(transform: Wrapped -> U) -> U? {

guard let x = self else { return nil }

return transform(x)

}

}

// 使用 map 来重写 incrementOptional

func incrementOptional2(optional: Int?) -> Int? {

return optional.map { $0 + 1 }

}

// 再谈可选绑定

//map 函数展示了一种操作可选值的方法,但是还有很多其它方法存在:

let x: Int? = 3

let y: Int? = nil

// 问题是加法运算只支持 Int 值,而不支持我们这里的 Int? 值

//let z: Int? = x + y 解决:

func addOptionals(optionalX: Int?, optionalY: Int?) -> Int? { if let x = optionalX {

if let y = optionalY {

return x + y

}

}

return nil

}

//了层层嵌套,我们还可以同时绑定多个可选:

func addOptionals_(optionalX: Int?, optionalY: Int?) -> Int? { if let x = optionalX, y = optionalY {

return x + y

}

return nil

}

// 想更简短,可以使用一个 guard 语句,当值缺失时提前退出:

func addOptionals__(optionalX: Int?, optionalY: Int?) -> Int?{

guard let x = optionalX, y = optionalY else {

return nil

}

return x + y

}

let capitals = [

"France": "Paris",

"Spain": "Madrid",

"The Netherlands": "Amsterdam", "Belgium": "Brussels"

]

// 为了编写一个能返回给定国家首都人口数量的函数,我们将 capitals 字典与之前定义的的cities 字典结合。对于每一次字典查询,我们必须确保它返回一个结果

func populationOfCapital(country: String) -> Int? {

guard let capital = capitals[country], population =  cities_[capital]

else { return nil }

return population * 1000

}

/**

可选链和if let(或guardlet)都是语言中让可选值能够更易于使用的特殊构造。不过,Swift 还提供了另一条途径来解决上述问题:那就是借力于标准库中的  flatMap 函数。多种类型中都 定义了 flatMap 函数,在可选值类型的情况下,它的定义是这样的

flatMap 函数检查一个可选值是否为 nil。若不是,我们将其传递给参数函数 f;若是 nil,那么

结果也将是 nil

*/

extension Optional {

func  flatMap<U>(f: Wrapped -> U?) -> U? {

guard let x = self else { return nil }

return f(x) }

}

// 使用此函数,重写例子

func addOptionals2(optionalX: Int?, optionalY: Int?) -> Int? {

return optionalX.flatMap {

x in optionalY.flatMap { y in return x + y}

}

}

func populationOfCapital2(country: String) -> Int? {

return capitals[country].flatMap {

capital in cities_ [ capital ].flatMap {

population in return population * 1000

}

}

}

// 当前我们通过嵌套的方式调用flatMap,取而代之,也可以通过链式调用来重写

//populationOfCapital2,这样使代码结构更浅显易懂:

func populationOfCapital3(country: String) -> Int? {

return capitals[country].flatMap {

capital in return cities_[capital]

}.flatMap {

population in return population * 1000

}

}
时间: 2024-10-12 13:08:07

swift 可选值的相关文章

【swift初见】Swift可选值Optionals

我们用oc开发的时候,经常会遇到null值的情况,如果不加任何判断的话可能会导致程序崩溃,swift语言添加了可选值这样的概念,基本语法如下: 可选类型: var optValue: Int? = 8 在类型后面加一个?表示optValue这个值可以为nil,"?"就是可选值的一个标记,?其实是一个Optionals的类型,我们可以看看swift的源码: enum Optional<T> : Reflectable, NilLiteralConvertible { case

Swift编程语言学习1.6——可选值

可选值 使用可选(optionals)来处理值可能缺失的情况.可选表示: 有值,等于 x   或者没有值 注意: C 和 Objective-C 中并没有可选这个概念.最接近的是 Objective-C 中的一个特性,一个方法要不返回一个对象要不返回nil,nil表示"缺少一个合法的对象".然而,这只对对象起作用--对于结构体,基本的 C 类型或者枚举类型不起作用.对于这些类型,Objective-C 方法一般会返回一个特殊值(比如NSNotFound)来暗示值缺失.这种方法假设方法的

关于swift的可选值(optional)

关于可选值optional 不同于OC,swift引入了一个新的概念——可选值,了解这个optional,对于swift的学习至关重要 概念定义:可以有值也可以没有值(nil)的一个类型.换句话说,它有两个状态:有值,没有值(nil) 按我的理解,可选值是带有布尔类型加持的普通类型 如何定义一个可选值呢? 上面的代码简单定义了一个叫做optionalValue的可选值. 和普通的变量定义没有太大区别,唯一不同在于,这里多了一个问号,?是对普通值的封包 要加在类型后面,也就是说,在变量或者常量的所

swift的可选值(optional)

苹果那文档写了一大堆也没有好好的写一下可选值(optional)这个东西.就是在有一个“Optional Chaining”的章节,但是也不是很充分的说明.最后找了半天在“the basics”里墨迹了几句.如果你没找到optional这个东西的话,那你可能也错过了一个很重要的东西,非optional类型的变量,这个变量的值不能是nil.这一点和ObjC以及其他的编程语言如C#.Java什么的差别很大. var example : String = "hello world" exam

Swift::3::可选值

可选值(Optional) 在OC,一个class类型的变量,其值既可为一个有效的对象,亦可为nil.但诸如Int,Double等类型则没有nil值.比如,32位Int,超过最大值后,OC 会用NSNotFound处理,而不是nil值.Swift 比OC 更为灵活,直接在语法层面支持所有类型佳能用nil值--可选值(Optional) 如何使用 使用可选值,Swift 提供了非常简洁的方式,直接在类型后加'?',例如定义一个有可选值的整型变量: var optionalInteger: Int?

窥探Swift之新添数据类型元组与可选值

今天的博客中就总结一下关于Swift中相对Objc新添加的两个数据类型:元组(Tuple)和可选值类型(Optional).上面这两个类型是Swift独有的类型,使用起来也是非常方便的,今天就通过一些示例来介绍一下如何初始化和使用元组和可选值类型以及使用元组和可选值类型的场景.废话少说,直奔主题,在今天的示例代码中仍然是使用Playground来测试的.左边是代码,右边是Playground中的结果. 一.Swift中的元组(Tuple) 元组类似于C语言中的结构体(Struct),用来存储一组

Swift之Optional 可选值

Optional 是 Swift 的一大特色,也是 Swift 初学者最容易困惑的问题 定义变量时,如果指定是可选的,表示该变量可以有一个指定类型的值,也可以是 nil 定义变量时,在类型后面添加一个 ?,表示该变量是可选的 变量可选项的默认值是 nil 常量可选项没有默认值,主要用于在构造函数中给常量设置初始数值 //: num 可以是一个整数,也可以是 nil,注意如果为 nil,不能参与计算 let num: Int? = 10 如果 Optional 值是 nil,不允许参与计算 只有解

Swift学习笔记(2)--元组(Tuples)、Optional(可选值)、(Assertions)断言

1.Tuples(元组) 元组是多个值组合而成的复合值.元组中的值可以是任意类型,而且每一个元素的类型可以是不同的. 1>定义:使用()包含所有元素,用逗号分开,也可以对每个元素做命名 ? 1 2 let http404Error = (404, "Not Found") let http200Status = (statusCode: 200, description: "OK")  //重命名 2>获取元素: a.部分获取:是需要部分元素,其余忽略的

可选值

在swift中可选值用于定义变量,可选值有两种状态:有数值,数值为空 (可选值可以用if语句进行判断) var optValue: Int? = 8; if optValue{//一般用于if中的只能为bool类型而此时用可选类型也是可以的 println(optvalue); } //对可选值进项强制解析(有一定的风险若将optValue赋值为空则此时运行时候就会报错) var svalue: Int = optValue! println(savlue); //一般情况下我们用可选绑定取代强