赞
踩
Expressions — The Swift Programming Language (Swift 5.7)
泛型使用
- @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
- @resultBuilder public struct ViewBuilder {
-
- /// Builds an empty view from a block containing no statements.
- public static func buildBlock() -> EmptyView
-
- /// Passes a single view written as a child view through unmodified.
- ///
- /// An example of a single view written as a child view is
- /// `{ Text("Hello") }`.
- public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
- }
表示属性
Attributes — The Swift Programming Language (Swift 5.7)
Swift公有“@”注解属性的全面介绍 - 迷你淘 - 博客园
Swfit 常用特性(Attribute)关键字_Code&Ocean的博客-CSDN博客
公有的Swift语言属性用“@”标记,类似于java中的注解,这些属性绝大多数都有正规的文档记载并且可以在代码中使用。我们接下来就对全部的公有属性进行介绍,其中的大多数属性看起来都很熟悉。
Key Path Expressions as Functions
- struct SomeStructure {
- var someValue: Int
- }
-
- let s = SomeStructure(someValue: 12)
- let pathToProperty = \SomeStructure.someValue
-
- let value = s[keyPath: pathToProperty]
- // value is 12
Expressions — The Swift Programming Language (Swift 5.7)
- for _ in 1...5 {
- print("Hello")
- }
输出:
Hello
Hello
Hello
Hello
Hello
for 循环里,如果不关心当前循环的位置,可以用_
- func greet(_ person: String, on day: String) -> String {
- return "Hello \(person), today is \(day)."
- }
- greet("John", on: "Wednesday")
不想设置函数参数标签,可以用_
- let coords = (1.0, 2.0, 0.5, 2.5)
- let (x, y, z, _) = coords
- print(x, y, z)
忽略元祖返回成员,可以用_
- 1_000_000 // instead of 1000000
- 0.000_000_001 // instead of 0.000000001
- 1_403_182_938 // instead of 1403182938
- 0.619_241_053 // instead of 0.619241053
增加数字的可读写,可以用_
- enum Action {
- case Driving(Int, Int)
- case Walking(Int, Int)
- func horizontalMovement() {
- switch self {
- case .Driving(let xSpeed, _):
- print("Driving \(xSpeed)mph in x-direction")
- case .Walking(let xSpeed, _):
- print("Walking \(xSpeed)mph in x-direction")
- default:
- fatalError("Unsupported")
- }
- }
- }
如果枚举变量里的某个值你不关系,可以通过_来跳过它
- let scores = [
- ("Alice", 3),
- ("Bob", 3),
- ("Charlie", 2),
- ("David", 3),
- ("Emmanuel", 2)
- ]
-
- let lessThanThree = scores.filter { (_, score) in return score < 3 }
-
- lessThanThree.forEach { (name, _) in print("\(name)") }
跟函数一样,闭包可以带参数。如果你将闭包传给操作collection的函数,你需要指定一个闭包参数和collection元素一致。
如果collection是由元祖组成的,你又不关系其中某个部分,可以用下划线(_)来替换。
- func giveName() -> String {
- return "Alice"
- }
-
- // 对函数返回值不感兴趣
- giveName()
-
- // 显示声明对函数返回值不感兴趣
- _ = giveName()
函数返回值
- class Pet {
- let name: String
- init(name: String) {
- self.name = name
- }
-
- func timeTo(_ command: String) {
- if command == "eat" { print("Yum!") }
- else if command == "sleep" { print("Zzz...") }
- }
- }
-
- class Cat: Pet {
- // Cat does not care about the command, let's skip it.
- override func timeTo(_ _: String) {
- print("Meow!")
- }
- }
-
- // Example calls:
- let dog = Pet(name: "Snoopy")
- dog.timeTo("sleep")
-
- let cat = Cat(name: "Luna")
- cat.timeTo("sleep")
函数参数标签可以替换为_
swift 设计思路:所有变量赋值时不能为nil,只要给变量赋值nil,就会抛出错误
- let intValue:Int = 0 // 合法
- let intValue2:Int = nil //不合法
- let optionalIntValue:Int? = nil //合法,這是一個Int的Optional
- // option 的定义
- enum Optional<T> {
- case None
- case Some(T)
- }
- //產生一個 iPad 2
- let 一台iPad2 = iPad(版本: "2", 使用者名字:"Grady Zhuo")
- let 禮物包裏:Optional = Optional.Some(一台iPad)
- let 沒有東西的包裏:Optional = Optional.None
-
- //或是也可以用以下寫法
- let 禮物包裏2:Optional = Optional(一台iPad2)
- let 沒有東西的包裏2:Optional = Optional()
关键字 ? 是语法糖,上面的代码可以写成
- let 一台iPad2 = iPad(版本: "2", 使用者名字:"Grady Zhuo")
- let 禮物包裏:iPad? = 一台iPad2
- let 沒有東西的包裏:iPad? = nil
由上面的例子可以发现, 关键字 ? 不止简化的定义,另外还简化了赋值的语法。不用再写Optional.Some(...)
、 Optional(...)
或 Optional.None
、 Optional()
。
放入 Optional 的過程,又叫 Wrapped ,也就是被包起來的意思。
有 4 + 1 种方式,以下我們會一一說明:
- //继续延续上面的例子
- //定义一个 拆开箱子 的泛型 function
- func 拆开箱子<箱子里的礼物>(箱子:Optional<箱子里的礼物>)->箱子里的礼物 {
- switch 箱子 {
- case .None:
- fatalError("里面没东西,是要气死谁?")
- case let .Some(礼物):
- return 礼物
- }
- }
-
- let iPad = 拆开箱子(礼物箱子) //拿到iPad
- let 没东西 = 拆开箱子(没有东西的箱子) //Crash,里面没东西,是要气死谁?
拆开箱子这个函数,swift使用语法糖 ! 来实现
只要在 Optional 的 wrappedValue 后面,划上一刀(加上!),就会执行类似上面的逻辑,并拆箱完成,但如果遇到 nil 的情况下,就会触发 Crash。
- //如果是有东西的箱子里
- let iPad = 礼物箱子里! //美而短小的美工小刀
- //如果是没有东西的箱子里
- let 没东西 = 没有东西的箱子里! //crash
- //如果是有东西的箱子里
- if 礼物箱子里 != nil {
- let 有iPad = 礼物箱子里!
- //拿iPad玩
- }
-
- //如果是没有东西的箱子里
- if 没有东西的箱子里 != nil {
- // 不会执行这裡
- } else{
- // 这裡会执行
- }
- //如果是有东西的箱子里
- if let iPad耶 = 礼物箱子里 {
- //拿iPad玩
- }
-
- //如果是没有东西的箱子里
- if let 没有东西耶 = 没有东西的箱子里 {
- // 不会执行这裡
- } else {
- // 这裡会执行
- }
优点:可以从第三方拆完直接拿到礼物,不用自已拆
缺点:比方法一迂回得多,但比方法二简洁一些
Swift 导入了一种 if let 的语法,除了可以判断是否是 nil ,也可以直接赋值到另一个变量上,可以看做是上面写法 if 判断后再用 let 赋值的合并语法,另外,此变量的作用域 (Scope) 与方法二一样,只在 if 的 {…} 里有效
- let 一台iPad:iPad
- //如果是有东西的箱子里
- if let iPad = 礼物箱子里 {
- 一台iPad = iPad
- } else {
- 一台iPad = iPad(版本: "2")
- }
- //玩iPad
- //上面 一台iPad 是 iPad裡的值
-
- let 另一台iPad:iPad
- //如果是没有东西的箱子里
- if let 如果有东西 = 没有东西的箱子里 {
- // 不会执行这裡
- 另一台iPad = 如果有东西
- } else {
- // 这裡会执行
- 另一台iPad = iPad(版本: "2")
- }
- //玩 另一台iPad
- //上面 一台iPad 是 新的iPad对象 ,是新产生的iPad
-
- //所以不论情况如何,都一定会有一台iPad可以运作。
Swift 导入了 ?? (Nil Coalescing Operator) 这个语法来简化 Unwrapping 的过程。 他的规则是,如果 ?? 左边有值,就取左边原本的值,如果左边是一个 nil ,那就改取右边的值。
?? 跟 ?: 很像,可以快速把检查与赋值一个语法完成,简单来说 这也是一个语法糖。
a ?? b // a if a is not nil else b
a ?? b 跟 a != nil ? a! : b 很像,可以快速把检查与赋值一个语法完成,简单来说 这也是一个语法糖。
- let 任何箱子里 = 礼物箱子里 ?? iPad(版本: "2") // 这裡会拿到礼物箱子里裡的礼物
- let 任何箱子里2 = 没有东西的箱子里 ?? iPad(版本: "2") // 这裡会拿到新iPad的实
- //定义 人 的类别
- class 人 {
- //这个人的姓名
- var 姓名:String?
- //这个人礼物收藏盒,也可能是空的
- var 礼物收藏盒:iPad?
-
-
- init(姓名:String?){
- self.姓名 = 姓名
- }
-
- //假如有人送礼物
- func 收礼物(礼物包裹:iPad?){
- // Unwrapping
- if let 礼物 = 礼物包裹 {
- 礼物.使用者名字 = self.姓名
- self.礼物收藏盒 = 礼物
- }
- }
- }
-
- //产生一个iPad2
- let iPad2:iPad? = iPad(版本: "2")
- //产生一个人
- let grady = 人(姓名:"Grady Zhuo")
- //把iPad2送给grady
- grady.收礼物(iPad2)
下面这个使用方法看看有没有问题?
let 使用者名字:String = grady.礼物收藏盒.使用者名字
这个语句编译阶段就会报错。因为“礼物收藏盒” 是 Optional 、“使用者名字” 也是 Optional , Optional 不等于内容物的类别,因此无法使用内容物的属性及方法。
[String]? 不等于 [String] ,所以 [String]? 无法使用 map() 或 appendElement()
所以在使用的时候,就要先一个 Optional 一个 Optional 解开后,才可以处理 Optional 里面的值。复习一下前面的 Unwrapping 手段来处理的话,有以下 3 种解法可以试试:
1. 用 ! 来进行 Optional 的 Unwrapping
- //这个写法,我是非常不建议的,因为很容易在过程中有nil发生,就引发crash。
- let 使用者名字:String = grady.礼物收藏盒!.使用者名字!
2. 用 if let 来进行 Optional 的Unwrapping
- if let 礼物 = grady.礼物收藏盒 {
- if let 使用者名字 = 礼物.使用者名字 {
- print("使用者名字:\(使用者名字)")
- }
- }
或是也可以使用 if let 提供的语法特性,一次解两个 Optional
- if let 礼物 = grady.礼物收藏盒, let 使用者名字 = 礼物.使用者名字 {
- //礼物和使用者名字都有值,才会进这个 scope
- print("使用者名字:\(使用者名字)")
- }
3. 用 Nil Coalescing Operator (??
)
- //如果礼物有值的情况,那使用者名字就会出现Grady Zhuo
- let 礼物 = grady.礼物收藏盒 ?? iPad(版本: "2")
- let 礼物所有人 = 礼物.使用者名字 ?? ""
- print("礼物所有人:\(礼物所有人)") //礼物所有人: Grady Zhuo
-
- //如果没有礼物,那使用者名字变成"No Owner"
- let 礼物2 = 人(姓名: "没有人").礼物收藏盒 ?? iPad(版本: "n")
- let 礼物所有人2 = 礼物2.使用者名字 ?? "No Owner"
- print("礼物所有人2:\(礼物所有人2)") //礼物所有人2: No Owner
-
-
-
- // ? 声明了一个Optional类型,它可能包含一个Int值,也可能什么都不包含
- // ? 可选的值是一个具体的值, 如果是 nil 以表示值缺失
-
- var num: Int?
-
-
- var optionalName: String? = "John Appleseed"
- var greeting = "Hello!"
- // 如果 optionalName 是 nil,条件会判断为 false,大括号中的代码会被跳过。
- // 如果不是 nil,会将值解包并赋给 name 常量,这样代码块中就可以使用这个值了。
- if let name = optionalName {
- greeting = "Hello, \(name)"
- }
- //一般if let的用法
- func 一般if的状况(optionalValue optionalValue: Int?)->String{
- if let unwrappedValue = optionalValue {
- // 有值
- // 解开的值会在 if let 的 scrope裡面
- return "\(optionalValue) : unwrappedValue:\(unwrappedValue)"
- }else{
- //如果 optionalValue 为 nil,就直接return
- return "\(optionalValue) : return"
- }
- }
-
- 一般if的状况(optionalValue: 123) //Optional(123) : unwrappedValue:\(unwrappedValue)
- 一般if的状况(optionalValue: nil) //nil : return
-
-
- //来看一下guard let 是怎麽用的
- func guard的状况(optionalValue optionalValue: Int?)->String{
- guard let unwrappedValue2 = optionalValue else {
- //与if let不一样,这个区块是条件不成立时,会被迫return
- return "\(optionalValue) : 强迫return"
- }
- // 解开的值会在 guard let 的 scrope外面
- return "\(optionalValue) : unwrappedValue2:\(unwrappedValue2)"
- }
-
- guard的状况(optionalValue: 123) //Optional(123) : unwrappedValue2:123
- guard的状况(optionalValue: nil) //nil : 强迫return
guard 跟 if 类似,也是做为条件判断的保留字,但 guard 是一种强制条件成立的语法,如果条件不成立,必须强制离开作用的 scope 。
另外guard let与 if let 不同的另一点是, Unwrapped Value 的 Scope 也不太一样
guard ... else {...}
如果解析错误,执行else,而不是抛出异常
参考:
five-common-questions-about-swift
一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
闭包的特点:
js里闭包的解释:闭包 - 廖雪峰的官方网站
闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。
- numbers.map({
- // 通过关键字 in 将(参数及返回值类型的声明)和(函数体)进行分离
- // 函数体为 闭包
- (number: Int) -> Int in
- let result = 3 * number
- return result
- })
- // 作为一个代理的回调,可以忽略参数,返回值
- // 单个语句闭包会把它语句的值当做结果返回
- // 用关键字 in 做区分参数和函数体(这里就一个语句)
- let mappedNumbers = numbers.map({ number in 3 * number })
- print(mappedNumbers)
解包是把集合里的元素赋值给变量
x, y = (1, 3)
问号❓:问号暗示包含的值是可选类型,也就是说可能包含某个类型的值也可能不包含值。
感叹号❗️:当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个惊叹号表示“我知道这个可选有值,请使用它。”这被称为可选值的强制解析。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。