swift Part 1

1 print 打印

swift 复制代码
print (1, 2, 3, 4, 5) // 1 2 3 4 5

print (1, 2, 3, 4, 5, separator: "_") // 1_2_3_4_5

print ("My name is Jake.", terminator:"--")
print ("My age is 18.")
// My name is Jake.--My age is 18.


let name = "小王"
print("你好\(name)")

2 值类型 vs 引用类型

在 Swift 中,值类型引用类型 的核心区别在于:赋值或传递时,是复制内容还是共享同一个实例

值类型 struct, enum, tuple(元祖)

  • 值类型赋值给var、let或者给函数传参,是直接将所有内容拷贝一份

  • 类似于对文件进行copy、paste操作,产生了全新的文件副本。属于深拷贝(deep copy)

引用类型 class, closure (闭包)

  • 引用赋值给var、let或者给函数传参,是将内存地址拷贝一份

  • 类似于制作一个文件的替身(快捷方式、链接),指向的是同一个文件。属于浅拷贝(shallow copy )

2.1 值类型赋值操作

swift 复制代码
// 1 字符串

var s1 = "Jack"

var s2 = s1

s2. append ("_Rose") 

print(s1) // Jack 

print(s2) // Jack_Rose
swift 复制代码
// 3 字典

var d1 = ["max": 10, "min" : 2]

var d2 = d1

d1["other"] = 7

d2 ["max"] = 12


print (d1) // ["other": 7, "max": 10, "min": 2]

print (d2) // ["max": 12, "min": 2]
swift 复制代码
// 结构体 struct

struct Point {
    var x: Int
    var y: Int
}

var point1 = Point(x: 0, y: 0)
var point2 = point1  // 复制
point2.x = 10

print(point1.x) // 0(未被修改)
print(point2.x) // 10

口 在Swift标准库中,为了提升性能,String、Array、Dictionary、Set采取了Copy On Write的技术

口 比如仅当有"写"操作时,才会真正执行拷贝操作

口 对于标准库值类型的赋值操作,Swift 能确保最佳性能,所有没必要为了保证最佳性能来避免赋值建

口 建议:不需要修改的,尽量定义成let

2.2 引用类型赋值

swift 复制代码
// 引用类型 - class

class Dog {
    var name: String
    init(name: String) { self.name = name }
}

let dog1 = Dog(name: "Buddy")
let dog2 = dog1  // 引用同一个对象
dog2.name = "Max"

print(dog1.name) // "Max"(被修改了)
print(dog2.name) // "Max"

15 函数定义在结构体, 类, 枚举中

一般把定义在枚举、结构体、类内部的函数,叫做方法

swift 复制代码
class Size {

  var width = 10

  var height = 10

  func show() {
      print("width=| (width), height=\ (height)")
  }
}

let s = Size()
s.show() // width=10, height=10
swift 复制代码
struct Point {

  var x = 10
  
  var y = 10

  func show() {
    print("x=\ (x), y=\ (y)")
  }
}

let p = Point ()

p.show()// ×=10,y=10
swift 复制代码
enum PokerFace : String {

  case spades = "黑桃", hearts = "红心", diamonds = "方片", clubs = "草花"

func show() {
  print("face is \(rawValue)")
}
}

let pf = PokerFace.hearts

pf.show() // face is "红心"

方法占用对象的内存么?

口不占用

口方法的本质就是函数

口方法、函数都存放在代码段

4 字面量

一句话总结:字面量就是你直接写在代码里的"原始数据",不需要计算就能知道它是什么。

swift 复制代码
// 字面量

let a = 10          // 10 是整数字面量
let b = 3.14        // 3.14 是浮点数字面量
let c = "Hello"     // "Hello" 是字符串字面量
let d = true        // true 是布尔字面量
let e = [1, 2, 3]   // [1, 2, 3] 是数组字面量
let f = ["a": 1]    // ["a": 1] 是字典字面量
swift 复制代码
// 非字面量

let y = x + 2       // x + 2 不是字面量(是表达式)
let z = Int("10")   // Int("10") 不是字面量(是函数调用)

5 区间运算

swift 复制代码
// 1 闭区间运算符
 let names = ["a", "b","c","d"]

 for i in 0...3 {
    print(names[i]) //a b c d
 }
swift 复制代码
// 2 半开区间运算符 
 for i in 0..<2 {  // a..<b 代表  a<=值<b
    print(name[i]) //a b
 }
swift 复制代码
// 3 单侧区间
 names[2...] // 2~3   2 到 最大
 names[...2] // 0~2   最小 到 2 
 names[..<2] // 0~1   最小 到 小于2
swift 复制代码
// 4 区间变量

 letrange = ...5 // -负无穷 到5
 
 print(range) // PartialRangeThrough<Int>(upperBound: 5)
 print(range.contains(7)) // false
 print(range.contains(-99)) // true
        
swift 复制代码
 // 5区间可以是Int 也可以是字符串
 
  let range = "a"..."z"// 打印字符串, 注意没指定类型就是字符串  从字符 a 到 z
  
  print(range.contains("f")) // true
  print(range.contains("F")) // false

6 switch语句

swift 复制代码
// 1 区别于 oc 可以不写break

 let number = 1
 
 switch number {
  case 1:
     print("1")
     break 
     
   case 2 :
      print("2")
     // break 可以不写,不会贯穿
     
   default:
      print("都不是")
   }
swift 复制代码
// 2 fallthrough 可以实现贯穿效果

var number = 1

switch number {

  case 1:
  print("'number is 1")
  fallthrough

  case 2:
  print ("number is 2")

  default:
  print ("number is other")
 }

  // number is 1
  // number is 2
swift 复制代码
// 3 区间匹配
let count = 62

switch count {
  case 0:
    print("none")
  case 1..<5:
    print("a few")
  case 5..<12:
    print("several")
  case 12..<100:
    print ("dozens of")
  case 100..<1000:
    print("hundreds of")
  default:
    print("many")
} 
// dozens of
swift 复制代码
// 4 元祖匹配
let point = (1, 1)

switch point {
  case (0, 0):
  print ("the origin")

case (_, 0):
  print("on the *-axis")

case (0, _):
  print("on the y-axis")

case (-2...2 ,-2...2):
  print("inside the box") 

default:
  print ("outside of the box")
}
// inside the box
swift 复制代码
// 5 符合条件

let string = "Jack"

 switch string {
   case "Jack":
     print("jack---")
      fallthrough

    case "Rose":
      print ("Right person")

    default:
      break
}

// jack---
// Right person


let string = "Jack"

switch string {
  case "Jack", "Rose": // 或
    print ("Right person")
    
  default:
    break
}
//  Right person


let character: Character = "a"

switch character {
  case "a", "A":
    print("The letter A")
    
  default:
    print("Not the letter A")
}

// The letter A
swift 复制代码
// 6 值绑定

enum Result { 
    case success(String, Int)
    case failure(String)
}

let result = Result.success("登录成功", 200)

switch result {
 case .success(let message, let code):
    print("成功: \(message), 代码: \(code)")
 case .failure(let error):
    print("失败: \(error)")
}
swift 复制代码
// 7 where 条件语句

let point = (1, -1)

switch point {
 case let (x, y) where x == y:
   print("on the line x == y")
 case let (x, y) where x == -y:
   print("on the line x == -y") // on the line x == -y
 case let (x, y) :
   print("(\(x), \(y)) is just some arbitrary point")
} 
swift 复制代码
// 7.1 将所有正数加起来

var numbers = [10,20,-10,-20,30,-30]
var sum = 0

for num in numbers where num > 0{ // 使用where来过滤num
  sum += num
}
print(sum) // 60

7 标签语句

swift 复制代码
// 普通 for循环的 break

for i in 1...3 {
    for j in 1...3 {
        if j == 2 {
            break  // 只跳出内层循环,外层继续
        }
        print("(\(i),\(j))")
    }
}
// 输出:(1,1) (2,1) (3,1)
// break 是跳出本次循环 当i = 1 j= 2 是后跳出i=1这循环, i = 2/3 同
swift 复制代码
// 添加标签的for循环 break

outer: for i in 1...3 {
    for j in 1...3 {
        if j == 2 {
            break outer  // 跳出整个外层循环
        }
        print("(\(i),\(j))")
    }
}
// 输出:(1,1)
// 遇到 j==2 后完全结束,不再继续

// 添加标签作用, 直接跳出整个循环 break outer

8 函数

swift 复制代码
// 函数定义

func funcname(形参) -> returntype
{
   Statement1
   Statement2
   ......
   Statement N
   return parameters
}

8.1 函数隐式返回

swift 复制代码
// 函数隐式返回:如果一个函数体是单行表达式,可以省略 return 关键字,函数会自动返回该表达式的值。

func sum(v1: Int, v2: Int) - Int {
  v1 + V2
}

sum(v1: 10, v2: 20) // 30

8.2 函数多返回值

swift 复制代码
// 通过元祖 实现函数多返回值

func calculate(v1: Int, V2: Int) -> (sum: Int, difference: Int, average: Int) {

  let sum = v1 + v2
  return (sum, v1 - v2, sum >> 1) 
}

  // sum >> 1 除以2的1次幂

let result = calculate (v1: 20, v2: 10)

result. sum // 30
result.difference // 10
result.average // 15

8.3 省略形参标签

swift 复制代码
// 使用下划线, 省略形参标签
func sum(_ v1: Int, _ v2: Int) -> Int {
  v1 + v2
}

sum (10, 20)

8.4 函数默认值

swift 复制代码
// 参数可以有默认值

func check(name: String = "nobody", age: Int, job: String = "none") {

print("name=\ (name), age=\ (age), job=\(job)")

}

check(name: "Jack", age: 20, job: "Doctor") // name=Jack, age=20, job=Doctor 

check(name: "Rose", age: 18) // name=Rose, age=18, job=none 

checklage: 10, job: "Batman"') // name=nobody, age=10, job=Batman 

check(age: 15) // name=nobody, age=15,

8.5 函数可变参数

swift 复制代码
// 可变参数

func sum _ numbers: Int...) →> Int {
 var total = 0

 for number in numbers {
   total += number
 }

 return total
}

sum (10, 20, 30, 40) // 100
swift 复制代码
// 一个函数最多只能有1个可变参数
// 紧跟在可变参数后面的参数不能省略参数标签

// 参数string不能省略标签

func test_ numbers: Int..., string: String, _ other: String) {
} 

test (10, 20, 30, string: "Jack", "Rose")

8.6 输入输出函数 inout

  • 可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值
swift 复制代码
// 可变参数不能标记为inout
// inout参数不能有默认值
// inout参数的本质是地址传递(引用传递)

func swapValues(_ V1: inout Int,- v2: inout Int){ 

  let tmp = v1
  v1 = v2
  v2 = tmp
}

var num1 = 10
var num2 = 20
swapValues (&num1, &num2)
swift 复制代码
func swapValues (_ v1: inout Int, _ V2: inout Int) {

 (v1, V2) = (v2, v1)

}

8.7 内联函数 @line

内联函数 debug默认未开启, release开启

以下函数不会触发内联函数

  • 1 函数体比较长
  • 2 包含递归调用
  • 3 包含动态派发(oc调用)
swift 复制代码
// 内联函数

func test(){
  print("哈哈")
}
test() // 开启内联函数, 即 test() 等价于调用 这句print("哈哈")
// 调用函数时候直接执行了函数的函数体
// 这样减少了调用函数的开销,开辟和回收栈空间
swift 复制代码
// 永远不会被内联(即使开启了编译器优化) @inline(never)

@inline(never)func test(){

 print("test") 
 
}
// 开启编译器优化后,即使代码很长,也会被内联(递归调用函数、动态派发的函数除外)@inline(__always)

@inline(__always)func test(){

 print ("test") 
 
}

8.8 函数类型

每一个函数都是有类型的,函数类型由形式参数类型、返回值类型组成

swift 复制代码
func test(){}
func test ()-> Void {}
func test ()->(){}

// 这三个等价 
swift 复制代码
func sum(a: Int, b: Int) -> Int {
 a + b
}
//(Int,Int)-> Int
swift 复制代码
// 定义变量
var fn:(Int,Int) -> Int = sumfn(2,3)

// 5,调用时不需要参数标签

8.9 函数类型作为函数参数

swift 复制代码
func sum(v1: Int,v2: Int)-> Int {

 v1 + v2

}

func difference(v1: Int, v2: Int) -> Int {

 v1 - v2

}

func printResult(_ mathFn: (Int, Int) - Int, _ a: Int, _ b: Int) {

 print("Result: \(mathFn(a, b) )")

}

printResult(sum, 5, 2) // Result: 7

printResult (difference, 5, 2) // Result: 3

8.9 函数类型作为函数返回值

swift 复制代码
func next|_ input: Int) → Int {

  input + 1

}

func previous (_ input: Int) -> Int {

  input - 1

}

func forward(_ forward: Bool) -> (Int) -> Int { // 看第一个尖号

  forward ? next : previous

}

forward (true) (3) // 4

forward (false)(3) // 2

8.10 嵌套函数

将函数定义在函数内部

swift 复制代码
func forward (

forward: Bool) - (Int) - Int {

  func next(_ input: Int) - Int {
    input + 1
  }

  func previous (_ input: Int) → Int {
    input - 1
  }
  
  return forward ? next : previous
}

forward(true) (3) // 4

forward (false) (3) // 2

9 别名typealise

typealias 用来给类型起别名

swift 复制代码
// 起别名
typealias Date = (year: Int, month: Int, day: Int)

func test (_ date: Date) {

  print (date.0)
  print (date.year)
}

test((2011,9,10))
swift 复制代码
// 按照Swift标准库的定义,Void 就是空元组()

public typealias Void = ()
swift 复制代码
typealias Date = (year: Int, month: Int, day: Int)

func test (_ date: Date) {

    print (date.1)
    print (date.year)
}

test((2021,9,10))

// 9
// 2021

9 枚举 (值类型)

1 枚举未指定类型, 则没有rawValue原始值, 也不能设置默认值

2 枚举指定类型, 会生成rawValue原始值

3 枚举关联值,主要场景是当模型用

4 内部声明计算属性,不能存储属性

5 枚举内能定义方法

6 枚举能继承协议 解析模型

9.1 基本用法

swift 复制代码
enum Direction {
    case east
    case south
    case west
    case north
}
swift 复制代码
// 错误使用! ! !

let dir =  Direction() // 报错!!! 没有可访问的初始化器()
swift 复制代码
// 正确使用
let east = Direction.east // 枚举名访问

print("\(east)----\(type(of: east))") // east----Direction

switch east {
case .east:
    print("西风")
case .south:
    print("南风")
case .west:
    print("西风")
case .north:
    print("北风")

}

9.2 原始值 rawValue

swift 复制代码
// 隐式原始值

enum grade: String {
      case perfect
      case great
      case good
      case bad
  }


print(grade.perfect.rawValue) // perfect
print(type(of: grade.perfect.rawValue)) // String
swift 复制代码
// 指定类型, 生成原始值

enum grade: String {
      case perfect = "A"
      case great = "B"
      case good = "C"
      case bad = "D"
  }
print(grade.perfect.rawValue) // A
print(grade.great.rawValue) // B
print(grade.good.rawValue) // C
print(grade.bad.rawValue) // D
swift 复制代码
//  枚举未指定类型, 则没有rawValue原始值, 也不能设置默认值

enum grade {
  case perfect = "sss" // 报错!!! 未指定枚举类型,不能设置默认值
  case great
  case good
  case bad
}

9.3 关联值

swift 复制代码
// 通过枚举关联值 保存网络请求数据

enum NetworkResponse {
    case success(Data)
    case failure(String)  
}

func fetchUserInfo(userId: Int, completion: @escaping (NetworkResponse) -> Void) {
    let url = URL(string: "https://api.example.com/user/\(userId)")!
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        // 统一处理所有错误
        if let error = error {
            completion(.failure(error.localizedDescription))
            return
        }
        
        guard let httpResponse = response as? HTTPURLResponse, 
                                 httpResponse.statusCode == 200, 
                                 let data = data else {
                                     completion(.failure("请求失败"))
                                     return
                                 }
        
        completion(.success(data))
    }.resume()
}

// 使用
fetchUserInfo(userId: 123) { response in
    switch response {
    case .success(let data):
        print("成功")
        // 解析 data
    case .failure(let error):
        print("失败: \(error)")
        if error == "请求失败" {
            // 可能需要登录或其他处理
        }
    }
}
swift 复制代码
// 通过结构体模型 保存网络请求数据

struct NetworkResponse {
    let isSuccess: Bool
    let data: Data?
    let errorMessage: String?
}

func fetchUserInfo(userId: Int, completion: @escaping (NetworkResponse) -> Void) {
    let url = URL(string: "https://api.example.com/user/\(userId)")!
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(NetworkResponse(isSuccess: false, data: nil, errorMessage: error.localizedDescription))
            return
        }
        
        guard let httpResponse = response as? HTTPURLResponse,
                                 httpResponse.statusCode == 200,
                                 let data = data else {
                                   completion(NetworkResponse(isSuccess: false, data: nil, errorMessage: "请求失败"))
                                   return
                                 }
        
        completion(NetworkResponse(isSuccess: true, data: data, errorMessage: nil))
    }.resume()
}

// 使用
fetchUserInfo(userId: 123) { response in
    if response.isSuccess, let data = response.data {
        print("成功")
        // 解析 data
    } else {
        print("失败: \(response.errorMessage ?? "未知错误")")
        if response.errorMessage == "请求失败" {
            // 可能需要登录或其他处理
        }
    }
}

9.4 遵守协议 ?????

swift 复制代码
// 6 枚举遵守协议
enum XXManType: RawRepresentable {
    // RawRepresentable(原始可代表) 
    // 这个协议需要自己实现一个  init?(rawValue: String)方法 和一个 rawValue属性
    // 作用通过rawValue值创建枚举, 枚举为可选类型, 创建失败为nil
    // 场景: 字典转模型

    case boy(title: String)
    case girl(title: String)

   //  初始化方法, 通过rawValue 创建
   typealias RawValue = String
    init?(rawValue: String) {
        switch rawValue {
        case "boy":
            self = .boy(title: "boy")
        case "girl":
            self = .girl(title: "girl")
        default:
            self = .boy(title: "boy")
        }
    }
    // rawValue 计算属性
    var rawValue: String {
        switch self {
        case .boy(let title):
            return title
        case .girl(let title):
            return title
        }
    }
}
// 字典转模型
class swiftModel: Mappable {
    var name: String = ""
    var age: String = ""
    var category: XXCertificateType = .marriage(title: "") // 对应一个枚举
    var man: XXManType = .boy(title: "") // 枚举变量

    // mappable 需实现方法
    required init?(map: Map) {
    }
     // mappable 需实现方法
    func mapping(map: Map) {
        name <- map["name"]
        age <- map["age"] // 赋值给字符串
        category <- map["category"] // 赋值给枚举
        man <- map["man"] // 赋值给枚举
        // man字符串, 通过rawValue赋值生成一个枚举
    }
}

10 可选项

*可选项 Optional: 是用来表示一个值可能存在,也可能不存在(nil)的类型;

包含普通可选 T?, 隐式解包 T!

  • 普通可选: 必须手动解包(!if let?? 等), 安全, 强制处理 nil

  • 隐式解包: 部分场景自动解包,部分需手动 ,方便, 但有崩溃风险 (隐式解包完全兼容, 普通可选的所有操作)

ps:

1 可选项: 就是定义个可以赋值为nil的类型; 2 隐式解包: 就是为解包提供方便, 可以隐式的解包, 但是仅仅部分场景

10.1 可选项声明

swift 复制代码
class ViewController: UIViewController {
    
    // MARK: - 属性声明
    // 普通可选
    var userName: String?
    var userAge: Int?
    var userAvatar: UIImage?
    
    var database: Database!      // 依赖注入,一定会初始化
    var config: Config!      // 依赖注入,一定会初始化
    var curTitle: String!
    
    // 隐式解包(常见于IBOulet)
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var nameTextField: UITextField!

10.2 可选项赋值

swift 复制代码
    // MARK: - 生命周期
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 给普通可选赋值
        userName = "张三"
        userAge = 25     
        
        // 给隐式解包赋值(模拟初始化)
        database = Database()
        config = Config()
        curTitle = "哈哈"
        
        // 调用各种使用场景
        demoOptionalUsage()
        demoImplicitUsage()
    }

10.3 普通可选使用

swift 复制代码
    // MARK: - 1. 普通可选的各种使用方式
    
    func demoOptionalUsage() {
        print("=== 普通可选示例 ===")
        
        // 方式1:可选链 (Optional Chaining) 
        let nameLength = userName?.count        // Int? 
        
        // 方式2:强制解包 (Forced Unwrapping) - 危险
        if userName != nil {
            let name = userName!                // String
        }
        
        // 方式3:可选绑定 (Optional Binding)
        if let name = userName {                 // String
            print("可选绑定: \(name), 长度: \(name.count)") // name只能在内部用
        }
        
        // 方式4:空合并运算符 (Nil Coalescing)
        let displayName = userName ?? "匿名用户"   // String
        print("空合并: \(displayName)") 
       
        // 方式5:guard let (提前退出)
        guard let age = userAge else {           // age是Int 
            return                        
        }
        print("年龄: \(age)") // age可以在外面用
        
        // 方式6:map方法
        let greeting = userName.map { "你好, \($0)" }  // String?
        print("map结果: \(greeting ?? "")")
        
        // 普通可选总结:
        
        // 普通可选项 使用需要解包后才能用
        // 解包方法: 强制解包, 可选绑定(guard 绑定), 空合并运算符 
    }

10.4 隐式解包使用

swift 复制代码
  // MARK: - 2. 隐式解包的各种使用方式
  
  func demoImplicitUsage() {
      print("\n=== 隐式解包示例 ===")
      
      // 方式1:直接访问(当作非可选使用)- 有崩溃风险
      let labelText = titleLabel.text           // String? (text本身是可选)
      print("直接访问: \(labelText ?? "")")  // titleLabel 为 UILabel?
      
      // 方式2:可选链(也可以用,返回可选)
      let textLength = titleLabel?.text?.count  // Int?
      print("可选链访问: \(textLength ?? 0)")
      
      // 方式3:可选绑定(推荐安全使用)
      if let db = database {                    // db是Database类型
          db.connect()
      }
      
      // 方式4:空合并运算符
      let dbName = database?.name ?? "默认数据库"  // String
      print("数据库名: \(dbName)")
      
      // 方式5:guard let
      guard let config = config else {
          return
      }
      config.load()
     
      
      // 触发隐式解包场景
      
      // 场景1
        print("\(type(of: database))") // Database?
        let name = database.name // String
        let sumstring = database.name + "史蒂芬" // String


        // 场景2
        print("\(type(of: curTitle))-") // String?
        let aa = curTitle + "aa"
        print("\(type(of: aa))-") //String
  }


      // MARK: - 辅助类
      class Database {
          var name: String = "主数据库"
          func connect() {
              print("数据库已连接")
          }
      }
      class Config {

        func load() {

        print("配置已加载")
    }
}

11 guard语句/ 卫兵语句

  • 1 当guard语句的条件为 false 时, 执行大括号里面的

  • 2 当guard语句的条件为 true 时, 就会跳过guard语句

  • 3 guard语句特别适合 "提前退出"

swift 复制代码
 guard 条件 else {
   // do something....
   退出当前作用域
   return
 }
 

当使用guard语句进行可选项绑定时,绑定的常量(let)、变量(var)也能在外层作用域中使用

swift 复制代码
func login(_ info: [String : String]) {
   guard let username = info ["username"] else {
     print("请输入用户名")
     return
   }
   
   guard let password = info["password"] else {
     print("请输入密码")
     return
   }
   
print("用户名:\(username)", "密码:\(password)", "登陆ing")

12 结构体 (值类型)

1 成员可以不设置默认初始值

2 编译器会自动生成初始化方法

3 如果自定义初始化方法,会覆盖系统创建的初始化方法

4 初始化需确保所有成员都有值

在Swift 标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小一部分

比如Bool、Int、Double、String、Array、 Dictionary等常见类型都是结构

swift 复制代码
struct Date {
 var year: Int // 可以设置初始值
 var month: Int
 var day: Int
}
var date = Date(year: 2019,month: 6, day: 23)// 初始化需确保,所有成员都有值

12.1 自定义初始化器

一旦在定义结构体时自定义了初始化器,编译器就不会再帮它自动生成其他初始化器

swift 复制代码
// 确保所有成员都初始化

struct Point {
    var x: Int
    var y: Int

}

var p1 = Point(x: 10, y: 10)
//  var p2 = Point (y: 10)
//  var p3 = Point(x: 10)
//  var p4 = Point()
swift 复制代码
// 编译器生成初始化器

struct Point {
    var x: Int = 0
    var y: Int = 0

//     init(x: Int, y: Int) {
//        self.x = x
//        self.y = y
//     }
}

var p1 = Point(x: 10, y: 10)
var p2 = Point (y: 10)
var p3 = Point(x: 10)
var p4 = Point()
swift 复制代码
// 自定义初始化器 覆盖了自动生成的初始化器

struct Point {
    var x: Int = 0
    var y: Int = 0

    init(x: Int, y: Int) {
      self.x = x
      self.y = y
    }
}

var p1 = Point(x: 10, y: 10)
//  var p2 = Point (y: 10)
//  var p3 = Point(x: 10)
//  var p4 = Point()

13 类 (引用类型)

1 成员须设置默认初始值 (或声明时候默认,或写在自定义初始化方法里)

2 会自动创建无参数初始化方法 class()

3 如果自定义初始化方法,会覆盖系统创建初始化方法

4 初始化需保证所有成员都有值

13.1 类 初始化成员

swift 复制代码
// 声明 直接默认初始值

class Man {
    var name: String = ""
    var height:String = ""
    var age: Int = 0
}
swift 复制代码
// 初始化器 默认初始值
class Man {
    var name: String
    var height:String
    var age: Int
    
    init(name: String = "", height: String = "", age: Int = 0) {
        self.name = name
        self.height = height
        self.age = age
    }
    
    // or
    
    init(name: String , height: String, age: Int) {
        self.name = ""
        self.height = ""
        self.age = 0
    }

}

14 闭包表达式

  • 闭包表达式, 就是函数, 匿名函数
swift 复制代码
// 闭包表达式 定义

{(参数, 参数) -> 返回值类型 in 
  函数体代码
}

// 注意函数体 没有return
// 闭包 必须指明, 或靠上下文推断

14.1 函数&闭包对比

swift 复制代码
// 函数 

func sum(_ v1: Int, _v2: Int) -> Int { 
  v1 + v2 
}

sum(10,20)
swift 复制代码
// 闭包

var fn = {(_ v1: Int, _ v2: Int) -> Int in
   v1 + v2
}

fn(10,20)
swift 复制代码
// 闭包

var fnValue = {(_ v1: Int, _ v2: Int) -> Int in
   v1 + v2
}(10,20)
swift 复制代码
// 实际应用
private lazy var zipRcodeImage: UIImageView  = {
    let image = UIImageView()
    return image
}()

// 无参数省略了 () in

14.2 闭包简写

swift 复制代码
// 声明函数, 入参包含一个函数, 没有返回值 !
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {

  print(fn (v1, v2))
}
swift 复制代码
// 1 基础写法

let fn1 = exec(v1: 10 , v2:20 , fn:{ (v1: Int, v2: Int) -> Int in 

  return v1 + v2
})

print(fn1) // ()

// 注意闭包的返回值 和函数的返回值不是一回事
swift 复制代码
// 2 去掉闭包类型, 包含入参, 返回值类型; 
// 闭包类型靠exec声明的类型推断 fn: (Int, Int) -> Int)

let fn1 = exec (v1: 10, v2: 20, fn: {

  v1, v2 in return v1 + v2
  
  // v1, v2 in v1 + v2
}
swift 复制代码
// 3 再次简化 去掉参数及返回值
// 闭包类型靠exec声明的类型推断 fn: (Int, Int) -> Int)

let fn1 = exec (v1: 10, v2: 20, fn: { $0 +$1 }

let fn1 = exec (v1: 10, v2: 20, fn: { + }

14.3 尾随闭包

  • 触发场景: 闭包表达式作为函数最后一个实参

  • 1 尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式

swift 复制代码
// 闭包表达式 非唯一参数

func exec(v1:Int,v2:Int,fn:(Int,Int)-> Int){

  print(fn (v1, v2))
}


// 正常写法
exec(v1: 10, v2: 10, fn:{ v1, v2 in
    v1 + v2
})

exec(v1: 10, v2: 10) { v1, v2 in
    v1 + v2
} // 编译器会为你自动转为 尾随闭包
  • 2 如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号
swift 复制代码
// 闭包表达式 唯一参数

func exec (fn: (Int, Int) -> Int) {
    print(fn (1, 2))
}

exec(fn: { $0 + $1 }) // 正常写法
 
exec(){ $0 + $1}

exec{ $0 + $1 }
swift 复制代码
// 数组排序方法(系统)

 func sort (by areInIncreasingOrder: (Element, Element) ->Bool
swift 复制代码
func cmp(i1: Int, i2: Int) -> Bool {
    // 大的排前面
    return i1 > i2
}

var nums = [11, 2, 18, 6, 5, 68, 45]

nums.sort (by: cmp) // num.sort { $0>$1 }

print(nums) // [68, 45, 18, 11, 6, 5, 2]

15 闭包

定义: 一个函数和它所捕获的变量\常量环境组合起来,称为闭包

  • 一般定义在函数内部的函数
  • 一般他捕获的是外层函数的局部变量/常量
swift 复制代码
typealias Fn = (Int) -> Int

func getFn() -> Fn {
    var num = 0
    func plus (_ i: Int) -> Int {
        num += i
        return num
    }
    return plus
}

let fn =  getFn()

print(fn(1)) // 1
print(fn(2)) // 3

getFn() 被调用:

  • 创建局部变量 num = 0(在栈上)
  • 定义嵌套函数 plus
  • 返回 plusplus 捕获了 numnum 从栈转移到堆上

② 第一次调用 fn(1)

  • 执行 num += 1num 从 0 → 1)
  • 返回 1

③ 第二次调用 fn(2)

  • 同一个闭包,同一个被捕获的 num
  • 执行 num += 2num 从 1 → 3)
  • 返回 3
相关推荐
Daniel_Coder7 小时前
iOS Widget 开发-14:iOS 18 控制中心组件开发
ios·swift·widget·activitykit·widgetkit·控制中心组件
sakiko_9 小时前
Swift学习笔记29-数据库SQlite
数据库·学习·sqlite·swift
2501_9159214310 小时前
使用Swift和Xcode创建简单iOS应用完整教程
ide·vscode·ios·个人开发·xcode·swift·敏捷流程
sakiko_1 天前
Swift学习笔记28-缓存
笔记·学习·swift
hhb_6181 天前
Swift技术难点梳理与实战案例解析
开发语言·ios·swift
Daniel_Coder1 天前
iOS Widget 开发-12:Widget 深度链接与导航
ios·swiftui·swift·widget·intents
Daniel_Coder1 天前
iOS Widget 开发-11:Widget 交互按钮实战(iOS 17+ App Intents)
ios·swiftui·swift·widget·link·appintents
东坡肘子1 天前
消失的 WWDC 愿望单 -- 肘子的 Swift 周报 #136
人工智能·swiftui·swift
浩宇软件开发2 天前
SwiftUI入门 10 分钟学会做一个 App 引导页
ios·swiftui·swift