swift-03-可选项&可选链

最近在学习swift,期间也看了不少教程和大神的博客,最后把笔记放这里,方便查看复习~swift

附上学习资料地址:w3cschool-Swift 教程YungFan大神的简书(推荐看一下,有些知识点总结地简直通俗易懂)数组

1、可选项

一、介绍

通俗一点来说,swift中的可选项与nil有关。安全

由于swift是强类型语言,nil也是一个特殊类型,因此说其余类型的数据不能直接赋值为nilmarkdown

若是遇到不肯定是否有值的类型,可使用可选项,那么这个类型只能两个取值:ni 或者 有一个肯定的值app

二、格式

常规写法ide

var name: Optional<String>
复制代码

经常使用语法糖的写法oop

//注意:在类型和 ? 之间没有空格
var name: String? 
复制代码

三、简单使用

给可选类型赋值学习

//声明一个可选项
var str: String? = nil
//赋值
str = "hello"
复制代码

取值ui

print(str) //Optional("hello")
复制代码

强制解包(!)取值url

//注意:这种作法不安全,只能用于 已经肯定str真的有值的状况,不然会崩溃 
print(str!) //hello
复制代码

强制解包安全作法

if str != nil {
    print(str!) //hello
}
复制代码

隐式解包

if let newStr = str {
    //此时输出的就是str的值,而不是Optional str
    print(newStr) //hello
}else{
    print("这个值是nil")
}
复制代码

守卫语句解包

//判断当语句=false,也就是newStr = nil,直接执行return,也有效防止了崩溃
guard let newStr = str else{
    return
}
print(newStr)
复制代码

四、应用场景

用可选项来接收URL,让代码更加严谨

// 正确写法:使用可选类型来接收
let url : URL? = URL(string: "https://www.baidu.com")
// 也能够这么写:该方式利用类型推断
let url1 = URL(string: "https://www.baidu.com")

// 经过url来建立request对象:在使用可选类型前要先进行判断是否有值
// 该语法成为可选绑定(若是url有值就解包赋值给tempURL,而且执行{})
if let tempUrl = url {
    let request = URLRequest(url: tempUrl)
}
复制代码

五、代码示例

/*
 主要做用于值缺失的状况,相似oc中某个对象=nil,在swift中只有可选项的常量或者变量才能使用nil
 可选项的标志:?

 nil:
 oc中,表示一个指向不存在对象的指针
 swift中,表示一种特殊类型,值缺失(不只仅对象类型,任何类型的可选项都能置为nil)
 */
var code: Int? = 100
code = nil
/*
var name: Int = 1000
name = nil
这种状况会报错,不是可选项
*/

/*
 使用感叹号:!
 一旦咱们知道可选项确定有一个值,那么为了拿到这个值,就要在可选项以后加上"!"来取值
 */
var age: Int? = 18
print("可选项确定有一个值:\(age!)")
        
复制代码

2、可选链

一、介绍

可选链 (Optional Chaining) 是一种能够请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为nil。

可选链返回两个值:

  • 若是目标有值,调用就会成功,返回该值
  • 若是目标为nil,调用将返回nil

屡次请求或调用能够被连接成一个链,若是任意一个节点为nil将致使整条链失效。

二、使用

经过在属性、方法、或下标脚本的可选值后面放一个问号(?),便可定义一个可选链。

2.1 可选链可替代强制解析

使用可选链'?': 将'?'放在可选值后面来调用方法、属性、下标脚本,当可选为nil的时候 输出比较友好的错误信息

使用强制解析'!': 将'!'放在可选值后面来调用方法、属性、下标脚本,用于强制展开值,当可选为nil的时候 强制展开会执行错误

代码示例:

class Residence {
    var numberOfRooms = 1
}

class Person {
    var residence: Residence?
}

let john = Person()

// ! 将致使运行时错误 :Fatal error: Unexpectedly found nil while unwrapping an Optional value (致命错误:在展开可选值时意外发现nil)
let roomCount = john.residence!.numberOfRooms

// ?连接可选residence?属性,若是residence存在则取回numberOfRooms的值
if let roomCount = john.residence?.numberOfRooms {
    print("John 的房间号为 \(roomCount)。")
} else {
    print("不能查看房间号")
}

打印:不能查看房间号
复制代码
2.2 可选链的调用

首先定义了4个类,包含了一个多层可选链

class Person {
    //住宅
    var residence: Residence?
}


class Residence {
    // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组
    var rooms = [Room]()
    var numberOfRooms: Int {
        return rooms.count
    }
    subscript(i: Int) -> Room {
        return rooms[i]
    }
    func printNumberOfRooms() {
        print("房间号为 \(numberOfRooms)")
    }
    var address: Address?
}

// Room 定义一个name属性和一个设定room名的初始化器
class Room {
    let name: String
    init(name: String) { self.name = name }
}

// 模型中的最终类叫作Address
class Address {
    //建筑名
    var buildingName: String?
    //建筑号
    var buildingNumber: String?
    //街道
    var street: String?
    func buildingIdentifier() -> String? {
        if (buildingName != nil) {
            return buildingName
        } else if (buildingNumber != nil) {
            return buildingNumber
        } else {
            return nil
        }
    }
}
复制代码
2.2.1 经过可选链调用方法
let john = Person()

if john.residence?.printNumberOfRooms() != nil {
    print("输出房间号")
} else {
    print("没法输出房间号")
}

打印:没法输出房间号
复制代码
2.2.2 经过可选链调用下标脚本

咱们能够经过可选链来获取下标脚本的值,可是不能经过可选链来设置下标脚本

let john = Person()

//?在这个位置的缘由是:john.residence 是可选链试图得到的可选值
if let firstRoomName = john.residence?[0].name {
    print("第一个房间名 \(firstRoomName).")
} else {
    print("没法检索到房间")
}
复制代码

再来看看给 john 赋个值

let john = Person()

let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "客厅"))
johnsHouse.rooms.append(Room(name: "厨房"))

john.residence = johnsHouse
 
let johnsAddress = Address()
johnsAddress.buildingName = "A123"
johnsAddress.street = "A123 Street"

john.residence!.address = johnsAddress

//获取下标脚本
if let firstRoomName = john.residence?[0].name {
    print("第一个房间名为\(firstRoomName)")
} else {
    print("没法检索到房间")
}

//打印:第一个房间名为客厅


//两层可选链
if let johnsStreet = john.residence?.address?.street {
    print("John 所在的街道是 \(johnsStreet)。")
} else {
    print("没法检索到地址。 ")
}

//打印:John 所在的街道是 A123 Street
复制代码
相关文章
相关标签/搜索