本文主要介绍Swift的闭包的使用并与OC的Block做比较。学习Swift是绕不过闭包的,因为无论是全局函数还是嵌套函数都是闭包的一种,本文主要介绍闭包表达式。

1.闭包表达式的使用

        // 1.定义一个闭包
let myClosure = {
(s1: String, s2:String) -> Bool
in
self.count = 10;
print("------");
return s1 > s2
}
print(count!);
// 2.调用闭包
let result = myClosure("Chris","Alex")
print("result = \(result)")
print("count = \(count!)")

日志

result = true
count = 10

总结 :1.和oc的block的声明和调用在形式上是极其类似的,不过闭包可以直接修改局部变量和全局变量的值,而block需要__block 关键字。

       // 3.Tralling 闭包(尾随)
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
( number) -> String in
var number = number
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
print(strings);

日志

["OneSix", "FiveEight", "FiveOneZero"]

2.Trailing 闭包

  函数的表现形式:(void)函数名(参数)。如果一个函数的最后一个参数是一个闭包,允许你写在参数所在哪个()外面。

(void)函数名(参数) {

};

如果只有闭包一个参数,括号可以省略。变成:

(void)函数名 {

};

当闭包里的代码很多的时候,这样写可以增加代码的可读性,多用于调用系统的函数。

  举例之前先介绍一下map函数,map属于Array的一个函数,调用这个函数需要传入一个闭包,返回一个新数组。Array里的每一个元素都会调用这个闭包,生成一个新对象,加入到新数组中。相当于 自动执行了for in和addobject两个方法,很实用。

let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

使用Trailing 闭包之前

let strings = numbers.map({
( number) -> String in
var number = number
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
})

使用Trailing 闭包之后

let strings = numbers.map{
( number) -> String in
var number = number
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}

  就一个参数不明显, 但是参数多了还是很有用的。因为闭包里的代码一般有很多,会导致包含参数的()距离太远。

3. 捕获: 解决嵌套函数的循环引用

func makeIncrementor(forIncrement amount: Int) -> () -> Int {

            var runningTotal = 0
func incrementor() -> Int {
// 只能捕获包含他的函数体内的变量或常量的值,建立一个副本,相当于深拷贝
// 新变量
runningTotal += amount
return runningTotal
}
print(" ----- runningTotal = \(runningTotal)")
return incrementor
} let incrementByTen = makeIncrementor(forIncrement: 10)
print("incrementor = \(incrementByTen())")
print("incrementor = \(incrementByTen())")
print("incrementor = \(incrementByTen())")

打印

 ----- runningTotal = 0
incrementor = 10
incrementor = 20
incrementor = 30

总结:incrementor的runningTotal就是对:incrementor的runningTotal的捕获。捕获有以下几个特点。

(1)捕获会生成一个新变量,和捕获变量的值相等,但内存不同,是引用类型,相当于OC中的深拷贝,新变量变化和捕获的变量没有任何关系了。因为incrementor的runningTotal的值一直没有改变。

(2)嵌套函数对新变量是强引用,只要嵌套函数还在,新变量就在,因为incrementor的返回值是一直增加的。

(3)如果不这样为什么会造成循环引用,incrementor对makeIncrementor变量runningTotal的引用就是对makeIncrementor的引用。运用捕获,就只是对runningTotal值的拷贝,不引用。

4.闭包传值

  在OC中我们用block最多的地方就是传值了,同样闭包也是。不过运用block和闭包传值最好是当对象只有一个状态的时候,如果对象状态很多最好用代理。

CycleScrollView 往CycleScrollViewViewController进行传值

import UIKit

// 定义闭包类型
typealias DidSelectItemClosureType = (Int) -> Void
class CycleScrollView: UIView, UICollectionViewDelegate,UICollectionViewDataSource {
// Mark:UICollectionViewDelegate
// 点击方法
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if self.didSelectItemClosure != nil {
// 13.利用闭包传值
self.didSelectItemClosure!(indexPath.row == 3 ? 0 : indexPath.row);
}
}
}

接收闭包传过来的值

import UIKit

class CycleScrollViewViewController: UIViewController {

    var cycleScrollView : CycleScrollView?
override func viewDidLoad() {
super.viewDidLoad()
createUI()
}
func createUI() { self.automaticallyAdjustsScrollViewInsets = false; cycleScrollView = CycleScrollView.init(frame: CGRect(x:0,y:64,width:ScreenWidth,height:ScreenHeight - 64))
// 闭包传值
cycleScrollView?.didSelectItemClosure = {
(index : Int) -> Void in print("您点击了第 \(index) 个")
}
self.view.addSubview(cycleScrollView!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning() }
}

  如果传值的例子有点没看懂,可以去下载我的DEMO,里面有详细的代码。闭包还是很厉害的,不需要我们进行任何操作就解决了循环引用问题,不像block还得对变量进行弱引用。本文部分内容是对Swift闭包详解的整理。

Swift应用案例 2.闭包入门到精通的更多相关文章

  1. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  2. Swift从入门到精通第十一篇 - 初始化 初识

    初始化(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 初始化 初始化是类.结构体.枚举生成实例的过程,为该类的每个存储属性设置初始值,有些在实例使用前的设置或初始化也可在此实现 ...

  3. Swift从入门到精通第八篇 - 方法 初识

    方法(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 方法 结构体.枚举.类都可以定义方法(实例方法.类型方法) 实例方法(Instance Methods) 实例方法只能用实例 ...

  4. redis入门到精通系列(二):redis操作的两个实践案例

    在前面一篇博客中我们已经学完了redis的五种数据类型操作,回顾一下,五种操作类型分别为:字符串类型(string).列表类型(list).散列类型(hash).集合类型(set).有序集合类型(so ...

  5. 《JAVA 从入门到精通》 - 正式走向JAVA项目开发的路

    以前很多时候会开玩笑,说什么,三天学会PHP,七天精通Nodejs,xx天学会xx ... 一般来说,这样子说的多半都带有一点讽刺的意味,我也基本上从不相信什么快速入门.我以前在学校的时候自觉过很多门 ...

  6. iOS回顾笔记(06) -- AutoLayout从入门到精通

    iOS回顾笔记(06) -- AutoLayout从入门到精通 随着iOS设备屏幕尺寸的增多,当下无论是纯代码开发还是Xib/StoryBoard开发,自动布局已经是必备的开发技能了. 我使用自动布局 ...

  7. 【PHP】最详细PHP从入门到精通(二)——PHP中的函数

     PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...

  8. 2017最新技术java高级架构、千万高并发、分布式集群、架构师入门到精通视频教程

    * { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...

  9. Javascript闭包入门(译文)

    前言 总括 :这篇文章使用有效的javascript代码向程序员们解释了闭包,大牛和功能型程序员请自行忽略. 译者 :文章写在2006年,可直到翻译的21小时之前作者还在完善这篇文章,在Stackov ...

随机推荐

  1. MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  2. php基础知识掌握——四种界定符

    闲来无事,研究了与java.c#完全不同的领域php,php即(外文名:PHP: Hypertext Preprocessor,中文名:"超文本预处理器"),对于学习php的初学者 ...

  3. Jquery动态增加行和删除行

    $("#add_5").click(function(){ var str_1="<tr> <td><input type=\"t ...

  4. Java集合框架之三:HashMap源码解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集合模型我们有必要弄清楚它的使用方法和它底层的实 ...

  5. 深入了解Unity中LineRenderer与TrailRenderer

    LineRender和TrailRender是两个好东西,很多Unity拖尾特效都会使用到它们.一些简单的介绍可以参见官方的API文档.在这里探讨一下它们具体的渲染方式,而后给出一些Shader以便更 ...

  6. Professional C# 6 and .NET Core 1.0 - Chapter 41 ASP.NET MVC

    What's In This Chapter? Features of ASP.NET MVC 6 Routing Creating Controllers Creating Views Valida ...

  7. .Net异步编程知多少

    1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法.异步编程说起来,大家可能都会说异步编程性能好.但好在哪里,引入了什么问题,以及如何使用,想必也未必能答的上来. 自 ...

  8. Android 增量更新

    title: Android NDK之增量更新 1.增量更新使用到的库bsdiff和bzip2 bsdiff库是一个开源的二进制差分工具,通过对比Apk的二进制,从而进行差分包的生成. bsdiff库 ...

  9. Javascript基础 - js中曾经忽略的知识点

    深入那些曾经忽略的Javascript知识 1. parseInt(string, [radix]),parseFloat(string) 一般我们省略第二个参数,parseInt(‘100’) == ...

  10. 做推送,怎么能不了解推送的 4 种消息形式呢?( Android 篇)

    极光推送是为 App 提供第三方推送服务的平台之一,它提供四种消息形式:通知,自定义消息,富媒体和本地通知. 笔者将基于官方说明与个人理解来谈一下这四种消息.本篇为 Android 篇,iOS 篇入口 ...