Swift-閉包

  • 閉包是自包含的功能代碼塊,可以在代碼中使用或者用來作為參數(shù)傳值。
  • 在Swift中的閉包與OC中的block類似。
 //閉包的表達(dá)式語法
/*
{(parameters) ->(return type) in
    statements
}
*/

//對(duì)整數(shù)進(jìn)行排序 sorted 后面就是閉包
let numbers = [1, 5, 9, 6, 2, 3, 4]
let newNumbers = numbers.sorted { (a, b) -> Bool in
    return a > b
}
print(newNumbers)  //結(jié)果是 [9, 6, 5, 4, 3, 2, 1]
  • 全局函數(shù)和嵌套函數(shù)其實(shí)就是特殊的閉包雳窟。
//設(shè)置全局方法獲取某些值
func kNaviBarHeight() -> Float {
    return 44
}

print(kNaviBarHeight())
  • 閉包的形式有:
  • (1)全局函數(shù)都是閉包,有名字但不能捕獲任何值。
  • (2)嵌套函數(shù)都是閉包封救,且有名字拇涤,也能捕獲封閉函數(shù)內(nèi)的值。
  • (3)閉包表達(dá)式都是無名閉包誉结,使用輕量級(jí)語法鹅士,可以根據(jù)上下文環(huán)境捕獲值。
  • Swift中的閉包有很多優(yōu)化的地方:
  • (1)根據(jù)上下文推斷參數(shù)和返回值類型
  • (2)從單行表達(dá)式閉包中隱式返回(也就是閉包體只有一行代碼惩坑,可以省略return)
  • (3)可以使用簡化參數(shù)名掉盅,如$0, $1(從0開始,表示第i個(gè)參數(shù)...)
  • (4)提供了尾隨閉包語法(Trailing closure syntax)
    */
// 以下閉包以Array的sorted函數(shù)為例
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ str1: String, _ str2: String) -> Bool {
    return str1 > str2
}

// sorted函數(shù)的參數(shù)是一個(gè)閉包以舒,下面?zhèn)髁艘粋€(gè)方法名趾痘,由此說明:嵌套函數(shù)是一個(gè)有名字但并可以捕獲其封閉函數(shù)域內(nèi)值的閉包
var reversedNames = names.sorted(by: backward)

// 普通閉包格式:(參數(shù): 參數(shù)類型,...) -> 返回值類型 in ...
reversedNames = names.sorted(by: { (str1: String, str2: String) -> Bool in
    return str1 > str2
})

// 根據(jù)Swift的類型推斷,參數(shù)類型及參數(shù)括號(hào)可以去掉蔓钟,返回值類型可以去掉
reversedNames = names.sorted(by: { str1, str2 in
    return str1 > str2
})

// 單行表達(dá)式:可以去掉return
reversedNames = names.sorted(by: {str1, str2 in
    str1 > str2
})

// 使用參數(shù)名縮寫:參數(shù)和in也可以去掉
reversedNames = names.sorted(by: {
    $0 > $1     //$0代表第1個(gè)參數(shù)永票, $1 代表第二個(gè)參數(shù)
})

// 使用運(yùn)算符:因?yàn)镾wift中為字符串重載了大于號(hào)小于號(hào)
reversedNames = names.sorted(by: >)

// 使用尾隨閉包:前提是閉包必須是函數(shù)的最后一個(gè)參數(shù)
reversedNames = names.sorted() {$0 < $1}

// 使用尾隨閉包:閉包是函數(shù)唯一參數(shù)時(shí),可以省掉參數(shù)括號(hào)
reversedNames = names.sorted {$0 < $1}

print(reversedNames)
  • 閉包值捕獲滥沫,閉包是引用類型
//sum 返回值是一個(gè)閉包 () -> Int
func sum(amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        print("runningTotal = \(runningTotal)")
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let addByTen = sum(amount: 10)

print("結(jié)果 \(addByTen())")
print("結(jié)果 \(addByTen())")

//打印結(jié)果
/*
runningTotal = 0
結(jié)果 10
runningTotal = 10
結(jié)果 20
*/
//兩次調(diào)用incrementer閉包是同一個(gè) runningTotal 被保留下來瓦侮,所以閉包是引用類型的
  • 逃逸閉包和非逃逸閉包
    如果這個(gè)閉包是在這個(gè)函數(shù)結(jié)束前內(nèi)被調(diào)用,就是非逃逸的即noescape佣谐。
    如果這個(gè)閉包是在函數(shù)執(zhí)行完后才被調(diào)用,調(diào)用的地方超過了這函數(shù)的范圍方妖,所以叫逃逸閉包狭魂。

例如:snapkit的添加約束的方法就是非逃逸的。因?yàn)檫@閉包馬上就執(zhí)行了

public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
        ConstraintMaker.makeConstraints(item: self.view, closure: closure)
    }

網(wǎng)絡(luò)請求請求結(jié)束后的回調(diào)的閉包則是逃逸的党觅,因?yàn)榘l(fā)起請求后過了一段時(shí)間后這個(gè)閉包才執(zhí)行雌澄。比如這個(gè)Alamofire里的處理返回json的completionHandler閉包,就是逃逸的杯瞻。

 public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
        delegate.queue.addOperation {
            (queue ?? DispatchQueue.main).async {
                var dataResponse = DefaultDataResponse(
                    request: self.request,
                    response: self.response,
                    data: self.delegate.data,
                    error: self.delegate.error,
                    timeline: self.timeline
                )

                dataResponse.add(self.delegate.metrics)

                completionHandler(dataResponse)
            }
        }

        return self
    }

舉個(gè)例子镐牺,寫一個(gè)模擬一個(gè)網(wǎng)絡(luò)請求,1秒才執(zhí)行魁莉,所以是逃逸閉包睬涧。

//此處編譯不通過
 func loadRequest(callBack: () -> Void) -> Void {
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) {
            callBack()
        }
    }

//下面是正確的寫法
func loadRequest(callBack: @escaping () -> Void) -> Void {
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 1) {
            callBack()
        }
    }

這樣就需要顯示的聲明@escaping才能編譯通過。

AD743289-18E8-43BC-8131-9B0C5D4A50C6.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旗唁,一起剝皮案震驚了整個(gè)濱河市畦浓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌检疫,老刑警劉巖讶请,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡延届,警方通過查閱死者的電腦和手機(jī)危彩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門勘究,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辫呻,“玉大人脑蠕,你說我怎么就攤上這事皿曲∷弑簦” “怎么了钞诡?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵郑现,是天一觀的道長。 經(jīng)常有香客問我荧降,道長接箫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任朵诫,我火速辦了婚禮辛友,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剪返。我一直安慰自己废累,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布脱盲。 她就那樣靜靜地躺著邑滨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钱反。 梳的紋絲不亂的頭發(fā)上掖看,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音面哥,去河邊找鬼哎壳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛尚卫,可吹牛的內(nèi)容都是我干的归榕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吱涉,長吁一口氣:“原來是場噩夢啊……” “哼刹泄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起怎爵,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤循签,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后疙咸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县匠,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乞旦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贼穆。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖兰粉,靈堂內(nèi)的尸體忽然破棺而出故痊,到底是詐尸還是另有隱情,我是刑警寧澤玖姑,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布愕秫,位于F島的核電站,受9級(jí)特大地震影響焰络,放射性物質(zhì)發(fā)生泄漏戴甩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一闪彼、第九天 我趴在偏房一處隱蔽的房頂上張望甜孤。 院中可真熱鬧,春花似錦畏腕、人聲如沸缴川。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽把夸。三九已至,卻和暖如春铭污,著一層夾襖步出監(jiān)牢的瞬間恋日,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工况凉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人各拷。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓刁绒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親烤黍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子知市,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 閉包是自包含的函數(shù)代碼塊,可以在代碼中被傳遞和使用速蕊。Swift 中的閉包與 C 和 Objective-C 中的代...
    窮人家的孩紙閱讀 1,708評(píng)論 1 5
  • 閉包可以從定義它們的上下文中捕獲和存儲(chǔ)對(duì)任何常量和變量的引用嫂丙。 這被稱為關(guān)閉這些常量和變量。 Swift處理所有的...
    Joker_King閱讀 592評(píng)論 0 2
  • Swift 中的閉包是自包含的函數(shù)代碼塊规哲,可以在代碼中被傳遞和使用跟啤。類似于OC中的Block以及其他函數(shù)的匿名函數(shù)...
    喬克_叔叔閱讀 522評(píng)論 1 3
  • * 閉包 是自包含的函數(shù)代碼塊,可以在代碼中被傳遞和使用。swift中的閉包和Objective-C中的代碼塊(b...
    EndEvent閱讀 856評(píng)論 4 8
  • 閉包是自包含的代碼塊隅肥,可以在代碼中被傳遞和使用竿奏。Swift中的閉包與C和Objective-C中代碼塊(block...
    Raaaaamsey閱讀 844評(píng)論 0 2