Swift5 函数与闭包

作者: 一粒咸瓜子 | 来源:发表于2020-09-12 21:06 被阅读0次

函数

是一种特殊的闭包

// 无参无返回值的三种写法
func a() -> Void { ... }
func a() -> () { ... } 
func a() { ... }  //最简


// 有参数无返回值
func square(a: Int, b: Int) -> Int { return a * b }
// 有参数有返回值
func square(a: Int, b: Int) { ... } //最简

内部函数

在函数体内部定义的函数,调用需在声明后

func result() {
    func sum(a: Int, b: Int) -> Int {
        return a + b
    }
    //在内部函数声明的下面调用
    print(sum(a: 20, b: 80))
}

外部参数及忽略

提供外部参数能增强函数的可读性,同时也能够让函数在内部使用参数更加简单
忽略外部参数用 “_” 表示

// frist/second表示外部参数,a标识函数的内部参数只能够在函数的内部使用
func sum(first a: Int, second b: Int) -> Int {
    return a + b
}
sum(first: 10, second: 20);

// 忽略外部参数 “_”
func sum(_ a: Int, _ b: Int) -> Int {
    return a + b
}
sum(10, 20);

函数小技巧

多返回值:元组类型

oc 中使用输出参数实现
使用元组来让一个函数返回多个值。该元组的元素可以用名称或数字来表示。

func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0
    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }
        sum += score
    }
    return (min, max, sum)
}
//let statistics: (min: Int, max: Int, sum: Int)
let statistics = calculateStatistics(scores:[5, 3, 100, 3, 9])
//或者print(statistics.2) 该元组的元素可以用名称或数字来表示
print(statistics)

不确定参数

oc 中使用 va_list 等宏实现
参数个数可变:函数可以带有可变个数的参数,这些参数在函数内表现为数组的形式

func nameFunc(names: String...) {
    for name in names {
        print(name, terminator: " ")
    }
}
nameFunc(names: "zhangsan", "lisi", "wangwu")
// Prints "zhangsan lisi wangwu "

闭包

closure:Swift 中的 block
闭包是一个封闭的结构: 闭包的参数,返回值、需要执行的代码片段 都应该在闭包的内部

函数和闭包都是引用类型:无论你将函数或闭包赋值给一个常量还是变量,你实际上都是将常量或变量的值设置为对应函数或闭包的引用

// block
void(^callback)(NSString *) = ^(NSString *str) {
    // code
}

// closure
let closure = { (str: String) -> () in
    // code
}

写法

一般左边不写,参数类型和返回值类型在闭包内标明即可

  • 无参无返回值
// 完整形式 左右都有 标明闭包类型
let closure:() -> () = { () -> () in  
    print("最简单的闭包完整形式")
}

// 简化:左边不写,右边标明闭包类型,返回值为空时,写()和 Void 一样 
let closure = { () -> Void in
    print("返回值为空时")
}

// 最简形式
let closure = {
    print("最简形式")
}
  • 有参无返回值
let closure = { (a: Int, b: Int) in
    print("\(a) + \(b) = \(a+b)")
}
  • 有参有返回值
let closure = { (a: Int, b: Int) -> (String) in
    return "\(a+b)"
}

尾随闭包

当函数的最后一个参数是闭包的时候,函数的参数的 '()' 可提前关闭。
如果函数只有闭包这一个参数, '()' 可以省略,如果闭包类型是无参无返回值,"() -> () in" 也可以省略。

是在调用函数的时候可以省略,而不是声明的时候

bug:如果写出来的闭包函数报错,可以在声明的时候把返回值写上,调用成功后再删除

func loadData(name: String, completed: (Int) -> ()) {
    completed((name as NSString).length)
}

loadData(name: "abc") { (count) in
    print("name's count = " + "\(count)")
}
//Prints "name's count = 3"

func cFunc(closure: () -> ()) {
    closure()
}
cFunc {             
    // code
}

@escaping

逃逸闭包:当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸。当你定义接受闭包作为参数的函数时,你可以在参数名之前标注 @escaping,⽤来指明这个闭包是允许“逃逸”出这个函数的

@escaping:标识该闭包可以逃离当前的“语境”,写在闭包类型声明之前,闭包作为函数的参数是默认不可逃逸的。

@escaping 语境:

  • 闭包在 async 需要逃逸、sync 不需要逃逸


  • 闭包被引用,需要逃逸。


循环引用

方法一:[weak self] (推荐)
self 是可选项,如果 self 已经被释放,则为 nil

// 类似 OC 中:__weak typeof(self) weakSelf;
// 如果 self 已经被释放,则为 nil
loadData { [weak self] in
    print("\(self?.view)")
}

方法二: [unowned self] (不推荐)
self 不是可选项,如果 self 已经被释放,则出现野指针访问

// 类似 OC 中:__unsafe_unretained typeof(self) weakSelf; 
// 如果 self 已经被释放,则出现野指针访问
loadData { [unowned self] in
    print("\(self.view)")
}

方法三:与 OC 类似

weak var weakSelf = self
loadData() {
    print("\(weakSelf?.view)")
}

网络请求试写

func request(urlStr: String, compeletd:@escaping (Bool, Any) -> Void) {
    guard let url = URL(string: urlStr) else {
        return
    }
    DispatchQueue.global().async {
        URLSession.shared.dataTask(with: url) { (data, _, error) in
            if error != nil {
                DispatchQueue.main.async {
                    compeletd(false, error!)
                }
            } else {
                let json = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers)
                DispatchQueue.main.async {
                    compeletd(true, json!)
                }
            }
        }.resume()
    }
}

相关文章

  • Swift5 函数与闭包

    函数 是一种特殊的闭包 内部函数 在函数体内部定义的函数,调用需在声明后 外部参数及忽略 提供外部参数能增强函数的...

  • 2018-07-10swift4与swift 3.3 语法重拾(

    函数与闭包 闭包

  • day14-函数(3)装饰器

    一、闭包函数 闭包函数=函数嵌套定义+函数对象+名称空间与作用域 闭包函数 1、闭:指的是该函数是定义在一个函数内...

  • rust 闭包与同步

    rust 闭包与同步 rust 闭包 rust闭包中主要包括两个部分,闭包参数和闭包环境变量。闭包函数和函数参数使...

  • 2019-01-05 闭包

    内部函数和外部函数中被内部函数调用的变量组成了闭包。 例子:函数line与变量a构成了闭包。 1.闭包似优化了变量...

  • 闭包

    闭包 闭包和函数的区别:闭包可以储存一部分变量,函数不能,函数传什么有什么值 函数与匿名函数的区别,匿名函数可以完...

  • Python闭包

    闭包 = 环境变量 + 函数 调用闭包内部的环境变量 闭包的经典误区 闭包与非闭包实现人类走路 非闭包 闭包

  • JavaScript中闭包与this对象

    闭包 闭包与匿名函数容易混淆。闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内...

  • 【JavaScript ES6 函数式编程入门经典】读书笔记(第

    第四章 闭包与高阶函数 4.1 理解闭包 简而言之,闭包就是一个内部函数,是在另一个函数内部的函数,比如 这就是闭...

  • 如何理解闭包?

    1、定义: 嵌套在函数作用域中的函数,称为闭包函数。该作用域称为闭包环境。通过闭包函数可以访问闭包函数所在函数作用...

网友评论

    本文标题:Swift5 函数与闭包

    本文链接:https://www.haomeiwen.com/subject/abtgektx.html