最近在学习swift,期间也看了不少教程和大神的博客,最后把笔记放这里,方便查看复习~swift
附上学习资料地址:w3cschool-Swift 教程 、 YungFan大神的简书(推荐看一下,有些知识点总结地简直通俗易懂)数组
通俗一点来说,swift中的可选项与nil
有关。安全
由于swift是强类型语言,nil也是一个特殊类型,因此说其余类型的数据不能直接赋值为nil
markdown
若是遇到不肯定是否有值的类型,可使用可选项,那么这个类型只能两个取值: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!)")
复制代码
可选链 (Optional Chaining)
是一种能够请求和调用属性、方法和子脚本的过程,用于请求或调用的目标可能为nil。
可选链返回两个值:
屡次请求或调用能够被连接成一个链,若是任意一个节点为nil将致使整条链失效。
经过在属性、方法、或下标脚本的可选值后面放一个问号(?),便可定义一个可选链。
使用可选链'?'
: 将'?'放在可选值后面来调用方法、属性、下标脚本,当可选为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("不能查看房间号")
}
打印:不能查看房间号
复制代码
首先定义了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
}
}
}
复制代码
let john = Person()
if john.residence?.printNumberOfRooms() != nil {
print("输出房间号")
} else {
print("没法输出房间号")
}
打印:没法输出房间号
复制代码
咱们能够经过可选链来获取下标脚本的值,可是不能经过可选链来设置下标脚本
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
复制代码