Swift-闭包

闭包是swift中非常重要的一个知识点。类似于objective-c中的block,其实函数就相当于一个特殊的闭包。闭包需要提前写好,在适当的时候再执行。

1、定义闭包

闭包的格式是(参数列表)->(返回值类型) in 实现代码

举一个最简单的例子。用常量记录一个代码块,按住option键就能看到,b1是一个闭包。再到适合的地方去调用它。


闭包1.png
let b1 = {
  print("干掉他们")
}
b1()

再来看一个带参数的闭包。在闭包中,参数、返回值和实现代码都是写在花括号里面的。in是用来定义分割和实现的。

let b2 = {
    (x:String)->() in print(x)
}

b2("string")

2、闭包案例

这个案例要模拟封装一个网络请求的类。利用闭包将jsonData类型的数据传递给展示页面。

  • 创建一个新的项目,选择swift语言


    闭包2.png
  • 封装一个网络请求的类HttpTool.swift继承自NSObject
  • 用异步线程模拟网络数据请求,再回到主线程中回调闭包
class HttpTool: NSObject {
    //闭包类型:(参数列表)->(返回值类型)
 
    func loadData(callback:@escaping(_ jsonData : String)->()) {
        DispatchQueue.global().async {
            print("发生网络请求:(Thread.current)")
        }
       
        DispatchQueue.main.async {
            ()->Void in
            print("获取到数据,并且回调:(Thread.current)")
           
            callback("jsonData数据")
        }
    }
}
  • 到需要接收数据的界面定义Httptool类的属性,设置一个初始化值,将初始值赋值给变量
  • 在swift中是不需要引入头文件的,文件之间可共享
import UIKit

class ViewController: UIViewController {

    var tools : HttpTool = HttpTool()
   
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        //用闭包将json数据拿到
        tools.loadData { (jsonData) ->() in
            print("在viewcontroller中拿到数据(jsonData)" )
        }
    }
}
闭包3.png

3、尾随闭包

尾随闭包用于需要将一个很长的闭包表达式作为最后一个参数传递给函数。也就是说如果按时的最后一个参数是闭包,那么在调用它的时候就可以把这个闭包写在括号外面,并紧跟括号,函数的其他参数则仍然写在括号之中。

//这个函数接受一个String和一个闭包
//函数体内调用闭包,并且将String作为参数传递给闭包
func myFunc(strP:String,closeP:(String)->Void) {
    closeP(strP)
}

//普通调用
myFunc(strP: "hello", closeP: {(string) in print(string)})
//尾随闭包
myFunc(strP: "hello") {
    (string) in print(string)
}

4、逃逸闭包

当一个闭包作为参数传到一个函数中,但是该闭包要在函数返回之后才被执行,于是就称这样的闭包为逃逸闭包。也就是说闭包逃离了函数的作用域。写法是在这个闭包参数前加一个@escaping用来指明这个闭包是允许逃逸出该函数的。

  • 声明一个方法,这个方法是一个逃逸闭包

  • 该方法要做的事情,就是将闭包添加到数组中去

//定义数组,里面的元素都是闭包类型的
var callBackArray : [()->Void] = []

//定义一个接收闭包的函数
func testEscapingClosure(callBack:@escaping ()-> Void) {
    callBackArray.append(callBack)
}
  • 当改变数组的时候,取第0个元素调用。此时就改变了变量x的值
class SomeClass {
    var x = 10
    
    func doSomething(){
        testEscapingClosure {
            self.x = 100
        }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
callBackArray.first?()
print(instance.x)

因为逃逸闭包是函数执行之后才会执行,所以可以这样理解:创建一个类的对象instance;在对象中初始化一个x=10;利用对象执行了函数doSomething;函数内部调用全局函数testEscapingClosure,期望修改instance对象的x值为100,但是此时并没有执行这个包含了赋值语句的闭包。

查找全局数组callBackArray,找到里面第一个元素,显然找到的是在testEscapingClosure函数中添加的闭包{self.x = 100},此时才通过全局数组的查询找出闭包并执行,于是x此时才被赋值为100。这就是在函数执行完毕后才执行闭包。刚好符合逃逸闭包的定义。

结论: 逃逸闭包将在函数执行之后执行,于是这段代码最后输出为100是因为闭包最后才被执行……

解决循环引用的三种方式

1、可以使用weak关键字将对象之间的联系变为弱引用

weak var weakself = self

2、第一种方式的简化

[weak self]

3、使用unowned解决

[unowned self]

但是该方法十分危险,要确保数据一定有值。否则会发生奔溃。

__weak 与__unretained有何区别?

__weak修饰的弱引用,如果指向的对象被销毁,那么指针会立马指向nil
__unretained修饰的弱引用,如果指向的对象被销毁,它的指针依然会指向之前的内存地址,很容易产生野指针(僵尸对象)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容

  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代...
    穷人家的孩纸阅读 1,656评论 1 5
  • 闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用。 这被称为关闭这些常量和变量。 Swift处理所有的...
    Joker_King阅读 563评论 0 2
  • Swift 中的闭包是自包含的函数代码块,可以在代码中被传递和使用。类似于OC中的Block以及其他函数的匿名函数...
    乔克_叔叔阅读 506评论 1 3
  • 中文文档 函数是特殊的闭包 Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:...
    伯wen阅读 157评论 0 0
  • 在OC中存储一段代码块可以使用Block,而对于Swift中也有相应的对照用于存储代码块这个就是今天所说的闭包,在...
    Mr_yinwei阅读 303评论 0 0