当前位置:   article > 正文

Swift 开发笔记 . ? ! optional @ <> \. Never_swift never

swift never

Expressions — The Swift Programming Language (Swift 5.7)


 

Never

<>

泛型使用

  1. @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
  2. @resultBuilder public struct ViewBuilder {
  3. /// Builds an empty view from a block containing no statements.
  4. public static func buildBlock() -> EmptyView
  5. /// Passes a single view written as a child view through unmodified.
  6. ///
  7. /// An example of a single view written as a child view is
  8. /// `{ Text("Hello") }`.
  9. public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
  10. }

@

表示属性

Attributes — The Swift Programming Language (Swift 5.7)

Swift公有“@”注解属性的全面介绍 - 迷你淘 - 博客园

Swfit 常用特性(Attribute)关键字_Code&Ocean的博客-CSDN博客

 公有的Swift语言属性用“@”标记,类似于java中的注解,这些属性绝大多数都有正规的文档记载并且可以在代码中使用。我们接下来就对全部的公有属性进行介绍,其中的大多数属性看起来都很熟悉。

\.

Key Path Expressions as Functions

  1. struct SomeStructure {
  2. var someValue: Int
  3. }
  4. let s = SomeStructure(someValue: 12)
  5. let pathToProperty = \SomeStructure.someValue
  6. let value = s[keyPath: pathToProperty]
  7. // value is 12

Expressions — The Swift Programming Language (Swift 5.7)

_

  1. for _ in 1...5 {
  2. print("Hello")
  3. }

输出:

Hello

Hello

Hello

Hello

Hello

for 循环里,如果不关心当前循环的位置,可以用_

  1. func greet(_ person: String, on day: String) -> String {
  2. return "Hello \(person), today is \(day)."
  3. }
  4. greet("John", on: "Wednesday")

不想设置函数参数标签,可以用_

  1. let coords = (1.0, 2.0, 0.5, 2.5)
  2. let (x, y, z, _) = coords
  3. print(x, y, z)

忽略元祖返回成员,可以用_

  1. 1_000_000 // instead of 1000000
  2. 0.000_000_001 // instead of 0.000000001
  3. 1_403_182_938 // instead of 1403182938
  4. 0.619_241_053 // instead of 0.619241053

增加数字的可读写,可以用_

  1. enum Action {
  2. case Driving(Int, Int)
  3. case Walking(Int, Int)
  4. func horizontalMovement() {
  5. switch self {
  6. case .Driving(let xSpeed, _):
  7. print("Driving \(xSpeed)mph in x-direction")
  8. case .Walking(let xSpeed, _):
  9. print("Walking \(xSpeed)mph in x-direction")
  10. default:
  11. fatalError("Unsupported")
  12. }
  13. }
  14. }

如果枚举变量里的某个值你不关系,可以通过_来跳过它

  1. let scores = [
  2. ("Alice", 3),
  3. ("Bob", 3),
  4. ("Charlie", 2),
  5. ("David", 3),
  6. ("Emmanuel", 2)
  7. ]
  8. let lessThanThree = scores.filter { (_, score) in return score < 3 }
  9. lessThanThree.forEach { (name, _) in print("\(name)") }

跟函数一样,闭包可以带参数。如果你将闭包传给操作collection的函数,你需要指定一个闭包参数和collection元素一致。

如果collection是由元祖组成的,你又不关系其中某个部分,可以用下划线(_)来替换。

  1. func giveName() -> String {
  2. return "Alice"
  3. }
  4. // 对函数返回值不感兴趣
  5. giveName()
  6. // 显示声明对函数返回值不感兴趣
  7. _ = giveName()

函数返回值

  1. class Pet {
  2. let name: String
  3. init(name: String) {
  4. self.name = name
  5. }
  6. func timeTo(_ command: String) {
  7. if command == "eat" { print("Yum!") }
  8. else if command == "sleep" { print("Zzz...") }
  9. }
  10. }
  11. class Cat: Pet {
  12. // Cat does not care about the command, let's skip it.
  13. override func timeTo(_ _: String) {
  14. print("Meow!")
  15. }
  16. }
  17. // Example calls:
  18. let dog = Pet(name: "Snoopy")
  19. dog.timeTo("sleep")
  20. let cat = Cat(name: "Luna")
  21. cat.timeTo("sleep")

函数参数标签可以替换为_

nil

swift 设计思路:所有变量赋值时不能为nil,只要给变量赋值nil,就会抛出错误

  1. let intValue:Int = 0 // 合法
  2. let intValue2:Int = nil //不合法
  3. let optionalIntValue:Int? = nil //合法,這是一個Int的Optional

Optional

  1. // option 的定义
  2. enum Optional<T> {
  3. case None
  4. case Some(T)
  5. }
  1. //產生一個 iPad 2
  2. let 一台iPad2 = iPad(版本: "2", 使用者名字:"Grady Zhuo")
  3. let 禮物包裏:Optional = Optional.Some(一台iPad)
  4. let 沒有東西的包裏:Optional = Optional.None
  5. //或是也可以用以下寫法
  6. let 禮物包裏2:Optional = Optional(一台iPad2)
  7. let 沒有東西的包裏2:Optional = Optional()

关键字 ? 是语法糖,上面的代码可以写成

  1. let 一台iPad2 = iPad(版本: "2", 使用者名字:"Grady Zhuo")
  2. let 禮物包裏:iPad? = 一台iPad2
  3. let 沒有東西的包裏:iPad? = nil

由上面的例子可以发现, 关键字 ? 不止简化的定义,另外还简化了赋值的语法。不用再写Optional.Some(...) 、 Optional(...) 或 Optional.None 、 Optional()

放入 Optional 的過程,又叫 Wrapped ,也就是被包起來的意思。

拆箱

有 4 + 1 种方式,以下我們會一一說明:

  • 使用美工小刀 (!)
  • 交给朋友检查 (if)
  • 交给第三方拆礼物 (if let)
  • 把自已变成具现化系 ( Assigned Value )
  • 交给第三方信託拆礼物,但 Scope 不同 (补充 5 : guard let)

  1. //继续延续上面的例子
  2. //定义一个 拆开箱子 的泛型 function
  3. func 拆开箱子<箱子里的礼物>(箱子:Optional<箱子里的礼物>)->箱子里的礼物 {
  4. switch 箱子 {
  5. case .None:
  6. fatalError("里面没东西,是要气死谁?")
  7. case let .Some(礼物):
  8. return 礼物
  9. }
  10. }
  11. let iPad = 拆开箱子(礼物箱子) //拿到iPad
  12. let 没东西 = 拆开箱子(没有东西的箱子) //Crash,里面没东西,是要气死谁?

拆开箱子这个函数,swift使用语法糖 ! 来实现

只要在 Optional 的 wrappedValue 后面,划上一刀(加上!),就会执行类似上面的逻辑,并拆箱完成,但如果遇到 nil 的情况下,就会触发 Crash。

  1. //如果是有东西的箱子里
  2. let iPad = 礼物箱子里! //美而短小的美工小刀
  3. //如果是没有东西的箱子里
  4. let 没东西 = 没有东西的箱子里! //crash

用if来实现

  1. //如果是有东西的箱子里
  2. if 礼物箱子里 != nil {
  3. let 有iPad = 礼物箱子里!
  4. //拿iPad玩
  5. }
  6. //如果是没有东西的箱子里
  7. if 没有东西的箱子里 != nil {
  8. // 不会执行这裡
  9. } else{
  10. // 这裡会执行
  11. }

用 if let 来实现

  1. //如果是有东西的箱子里
  2. if let iPad耶 = 礼物箱子里 {
  3. //拿iPad玩
  4. }
  5. //如果是没有东西的箱子里
  6. if let 没有东西耶 = 没有东西的箱子里 {
  7. // 不会执行这裡
  8. } else {
  9. // 这裡会执行
  10. }

优点:可以从第三方拆完直接拿到礼物,不用自已拆
缺点:比方法一迂回得多,但比方法二简洁一些
Swift 导入了一种 if let 的语法,除了可以判断是否是 nil ,也可以直接赋值到另一个变量上,可以看做是上面写法 if 判断后再用 let 赋值的合并语法,另外,此变量的作用域 (Scope) 与方法二一样,只在 if 的 {…} 里有效

?实现

  1. let 一台iPad:iPad
  2. //如果是有东西的箱子里
  3. if let iPad = 礼物箱子里 {
  4. 一台iPad = iPad
  5. } else {
  6. 一台iPad = iPad(版本: "2")
  7. }
  8. //玩iPad
  9. //上面 一台iPad 是 iPad裡的值
  10. let 另一台iPad:iPad
  11. //如果是没有东西的箱子里
  12. if let 如果有东西 = 没有东西的箱子里 {
  13. // 不会执行这裡
  14. 另一台iPad = 如果有东西
  15. } else {
  16. // 这裡会执行
  17. 另一台iPad = iPad(版本: "2")
  18. }
  19. //玩 另一台iPad
  20. //上面 一台iPad 是 新的iPad对象 ,是新产生的iPad
  21. //所以不论情况如何,都一定会有一台iPad可以运作。

Swift 导入了 ?? (Nil Coalescing Operator) 这个语法来简化 Unwrapping 的过程。 他的规则是,如果 ?? 左边有值,就取左边原本的值,如果左边是一个 nil ,那就改取右边的值。

?? 跟 ?: 很像,可以快速把检查与赋值一个语法完成,简单来说 这也是一个语法糖。
 

a ?? b // a if a is not nil else b

a ?? b 跟 a != nil ? a! : b 很像,可以快速把检查与赋值一个语法完成,简单来说 这也是一个语法糖。

  1. let 任何箱子里 = 礼物箱子里 ?? iPad(版本: "2") // 这裡会拿到礼物箱子里裡的礼物
  2. let 任何箱子里2 = 没有东西的箱子里 ?? iPad(版本: "2") // 这裡会拿到新iPad的实

Optional Chaining (?.) 

  1. //定义 人 的类别
  2. class 人 {
  3. //这个人的姓名
  4. var 姓名:String?
  5. //这个人礼物收藏盒,也可能是空的
  6. var 礼物收藏盒:iPad?
  7. init(姓名:String?){
  8. self.姓名 = 姓名
  9. }
  10. //假如有人送礼物
  11. func 收礼物(礼物包裹:iPad?){
  12. // Unwrapping
  13. if let 礼物 = 礼物包裹 {
  14. 礼物.使用者名字 = self.姓名
  15. self.礼物收藏盒 = 礼物
  16. }
  17. }
  18. }
  19. //产生一个iPad2
  20. let iPad2:iPad? = iPad(版本: "2")
  21. //产生一个人
  22. let grady = 人(姓名:"Grady Zhuo")
  23. //把iPad2送给grady
  24. grady.收礼物(iPad2)

下面这个使用方法看看有没有问题?

let 使用者名字:String = grady.礼物收藏盒.使用者名字

这个语句编译阶段就会报错。因为“礼物收藏盒” 是 Optional 、“使用者名字” 也是 Optional , Optional 不等于内容物的类别,因此无法使用内容物的属性及方法。

[String]? 不等于 [String] ,所以 [String]? 无法使用 map() 或 appendElement() 

 所以在使用的时候,就要先一个 Optional 一个 Optional 解开后,才可以处理 Optional 里面的值。复习一下前面的 Unwrapping 手段来处理的话,有以下 3 种解法可以试试:

1. 用 ! 来进行 Optional 的 Unwrapping

  1. //这个写法,我是非常不建议的,因为很容易在过程中有nil发生,就引发crash。
  2. let 使用者名字:String = grady.礼物收藏盒!.使用者名字!

2. 用 if let 来进行 Optional 的Unwrapping

  1. if let 礼物 = grady.礼物收藏盒 {
  2. if let 使用者名字 = 礼物.使用者名字 {
  3. print("使用者名字:\(使用者名字)")
  4. }
  5. }
或是也可以使用 if let 提供的语法特性,一次解两个 Optional
  1. if let 礼物 = grady.礼物收藏盒, let 使用者名字 = 礼物.使用者名字 {
  2. //礼物和使用者名字都有值,才会进这个 scope
  3. print("使用者名字:\(使用者名字)")
  4. }

3. 用 Nil Coalescing Operator (??)

  1. //如果礼物有值的情况,那使用者名字就会出现Grady Zhuo
  2. let 礼物 = grady.礼物收藏盒 ?? iPad(版本: "2")
  3. let 礼物所有人 = 礼物.使用者名字 ?? ""
  4. print("礼物所有人:\(礼物所有人)") //礼物所有人: Grady Zhuo
  5. //如果没有礼物,那使用者名字变成"No Owner"
  6. let 礼物2 = 人(姓名: "没有人").礼物收藏盒 ?? iPad(版本: "n")
  7. let 礼物所有人2 = 礼物2.使用者名字 ?? "No Owner"
  8. print("礼物所有人2:\(礼物所有人2)") //礼物所有人2No Owner

  1. // ? 声明了一个Optional类型,它可能包含一个Int值,也可能什么都不包含
  2. // ? 可选的值是一个具体的值, 如果是 nil 以表示值缺失
  3. var num: Int?
  4. var optionalName: String? = "John Appleseed"
  5. var greeting = "Hello!"
  6. // 如果 optionalName 是 nil,条件会判断为 false,大括号中的代码会被跳过。
  7. // 如果不是 nil,会将值解包并赋给 name 常量,这样代码块中就可以使用这个值了。
  8. if let name = optionalName {
  9. greeting = "Hello, \(name)"
  10. }

guard let

  1. //一般if let的用法
  2. func 一般if的状况(optionalValue optionalValue: Int?)->String{
  3. if let unwrappedValue = optionalValue {
  4. // 有值
  5. // 解开的值会在 if let 的 scrope裡面
  6. return "\(optionalValue) : unwrappedValue:\(unwrappedValue)"
  7. }else{
  8. //如果 optionalValue 为 nil,就直接return
  9. return "\(optionalValue) : return"
  10. }
  11. }
  12. 一般if的状况(optionalValue: 123) //Optional(123) : unwrappedValue:\(unwrappedValue)
  13. 一般if的状况(optionalValue: nil) //nil : return
  14. //来看一下guard let 是怎麽用的
  15. func guard的状况(optionalValue optionalValue: Int?)->String{
  16. guard let unwrappedValue2 = optionalValue else {
  17. //if let不一样,这个区块是条件不成立时,会被迫return
  18. return "\(optionalValue) : 强迫return"
  19. }
  20. // 解开的值会在 guard let 的 scrope外面
  21. return "\(optionalValue) : unwrappedValue2:\(unwrappedValue2)"
  22. }
  23. guard的状况(optionalValue: 123) //Optional(123) : unwrappedValue2:123
  24. guard的状况(optionalValue: nil) //nil : 强迫return

guard 跟 if 类似,也是做为条件判断的保留字,但 guard 是一种强制条件成立的语法,如果条件不成立,必须强制离开作用的 scope 。

另外guard let与 if let 不同的另一点是, Unwrapped Value 的 Scope 也不太一样

guard

guard ... else {...}

如果解析错误,执行else,而不是抛出异常

参考:

初學Swift:愛恨交織的 Optional

five-common-questions-about-swift

闭包Closure Wrapped

一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

闭包的特点:

  • 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  • 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

js里闭包的解释:闭包 - 廖雪峰的官方网站

闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。

  1. numbers.map({
  2. // 通过关键字 in 将(参数及返回值类型的声明)和(函数体)进行分离
  3. // 函数体为 闭包
  4. (number: Int) -> Int in
  5. let result = 3 * number
  6. return result
  7. })
  1. // 作为一个代理的回调,可以忽略参数,返回值
  2. // 单个语句闭包会把它语句的值当做结果返回
  3. // 用关键字 in 做区分参数和函数体(这里就一个语句)
  4. let mappedNumbers = numbers.map({ number in 3 * number })
  5. print(mappedNumbers)

解包Unpacking Unwrap

解包是把集合里的元素赋值给变量

x, y = (1, 3)

!?

问号❓:问号暗示包含的值是可选类型,也就是说可能包含某个类型的值也可能不包含值。

感叹号❗️:当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个惊叹号表示“我知道这个可选有值,请使用它。”这被称为可选值的强制解析。

Swift的問號與驚嘆號:可有可無的 Optional

swift学习笔记 问号❓与感叹号❗️ - 简书

参考:

官方文档

SwifGG 

一篇入门swift的学习笔记___MrCool的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/780865
推荐阅读
  

闽ICP备14008679号