Swift基礎(chǔ)-04(函數(shù) 閉包)

1.Swift中函數(shù)的使用
  • 函數(shù)的定義
  /// 函數(shù)格式,格式 函數(shù)名(形參列表) -> 返回值
    func demo(x: Int, y: Int) -> Int {
        return x + y
    }
//  print(demo(x: 2, y: 3))
  • 外部參數(shù)
    // 外部參數(shù)
    /// 外部參數(shù)就是在形參前面添加一個(gè)名字
    /// 外部參數(shù)不會(huì)影響內(nèi)部的細(xì)節(jié)
    /// 外部參數(shù)會(huì)讓外部調(diào)用方看起來(lái)更加的直觀
    func demo1(num1 x: Int,num1 y: Int) -> Int {
        return x + y
    }
// print(demo1(num1: 2, num1: 3))
  • _的使用
    // 外部參數(shù)
    /// _ 外部參數(shù)如果使用 _ 在外部調(diào)用函數(shù)時(shí)會(huì)忽略形參的值
    /// _ 在Swift中 就是可以忽略任意不感興趣的值
    func demo2(_ x: Int, _ y: Int) -> Int {
        return x + y
    }
//  print(demo2(2, 3));
  • 常見(jiàn)的 "_" 在for循環(huán)中
 /// Immutable value 'i' was never used; consider replacing with '_' or removing it
    /// i 從來(lái)沒(méi)有用到 建議使用 _ 替代
    func demo3()  {
        for i in 0...10 {
            print("洋蔥數(shù)學(xué)")
        }
        for _ in 0...10 {
            print("洋蔥數(shù)學(xué)")
        }
    }
  • 函數(shù)的默認(rèn)值
    // 函數(shù)的默認(rèn)值
    // 通過(guò)給參數(shù)設(shè)置默認(rèn)值掉冶,在調(diào)用的時(shí)候,可以任意組合參數(shù)凌蔬,如果不指定莺掠,就是用默認(rèn)值
    // OC中需要定義很多的方法衫嵌,以及實(shí)現(xiàn)方法,最終調(diào)用包含所有參數(shù)的那個(gè)方法
    // OC中可以看SDWebImage分類(lèi) 為圖片添加分類(lèi)
    func demo4(x: Int = 1, y: Int = 2) -> Int {
        return x + y
    }
        print(demo4())
        print(demo4(x: 10, y: 20))
        print(demo4(x: 10))
        print(demo4(y: 20))
  • 無(wú)返回值的函數(shù)的用
   // 無(wú)返回值的函數(shù)值
    /**
        三種方式
        ->直接省略 
        ->()
        ->Void
     */
    func demo5() {  // func demo5() - () 或者 func demo7() -> Void
        print("哈哈")
    }
  • 返回多個(gè)值的函數(shù)
   /// “使用元組來(lái)讓一個(gè)函數(shù)返回多個(gè)值彻秆。該元組的元素可以用名稱(chēng)或數(shù)字來(lái)表示楔绞。”
    func demo(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)
    }
// 調(diào)用 print(demo(scores: [1,4,7])) 
// 輸出 (min: 1, max: 7, sum: 12)
  • 可變參數(shù)的函數(shù)
 func sumOf(numbers: Int...) -> Int {
        var sum = 0
        for number in numbers {
            sum += number
        }
        return sum
    }
//  sumOf()
//  sumOf(numbers: 42, 597, 12)
  • 函數(shù)作為返回值的情況
 func makeIncrementer() -> ((Int) -> Int) {
        func addOne(number: Int) -> Int {
            return 1 + number
        }
        return addOne
    }
  // var increment = makeIncrementer()
  // increment(7)
  • 函數(shù)作為參數(shù)的情況
    func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
        for item in list {
            if condition(item) {
                return true
            }
        }
        return false
    }
    
    func lessThanTen(number: Int) -> Bool {
        return number < 10
    }
//    var numbers = [20, 19, 7, 12]
//    hasAnyMatches(list: numbers, condition: lessThanTen)
  • 輸入輸出參數(shù)
    數(shù)參數(shù)默認(rèn)是常量唇兑。試圖在函數(shù)體中更改參數(shù)值將會(huì)導(dǎo)致編譯錯(cuò)誤(compile-time error)酒朵。這意味著你不能錯(cuò)誤地更改參數(shù)值。如果你想要一個(gè)函數(shù)可以修改參數(shù)的值扎附,并且想要在這些修改在函數(shù)調(diào)用結(jié)束后仍然存在蔫耽,那么就應(yīng)該把這個(gè)參數(shù)定義為輸入輸出參數(shù)(In-Out Parameters)。
    定義一個(gè)輸入輸出參數(shù)時(shí)留夜,在參數(shù)定義前加inout關(guān)鍵字匙铡。一個(gè)輸入輸出參數(shù)有傳入函數(shù)的值,這個(gè)值被函數(shù)修改碍粥,然后被傳出函數(shù)鳖眼,替換原來(lái)的值。
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

swapTwoInts(::) 函數(shù)簡(jiǎn)單地交換 a 與 b 的值嚼摩。該函數(shù)先將 a 的值存到一個(gè)臨時(shí)常量 temporaryA 中钦讳,然后將 b 的值賦給 a,最后將 temporaryA 賦值給 b枕面。
你可以用兩個(gè) Int 型的變量來(lái)調(diào)用 swapTwoInts(::)愿卒。需要注意的是,someInt 和 anotherInt 在傳入 swapTwoInts(::) 函數(shù)前膊畴,都加了 & 的前綴:

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// 打印 "someInt is now 107, and anotherInt is now 3
2.Swift中閉包
  • 使用常量記錄函數(shù)
  // 使用常量記錄函數(shù)
    func demo() {
        print(sum(x: 10, y: 20));
        // f 的類(lèi)型  (Int, Int) -> Int
        let f = sum
        print(f(30, 40))
    }

    func sum(x: Int, y: Int) -> Int {
        return x + y
    }
  • 簡(jiǎn)單的閉包
    func demo2() {
        // 沒(méi)有參數(shù)和返回值掘猿,可以省略病游,連 in 都可以省略
        // b1: () -> ()
        let b1 = {
            print("hello")
        }
        // 執(zhí)行閉包
        b1()
        
        // 在OC中的寫(xiě)法,可以對(duì)比一下
        /**
         void (^b1) = ^{
            NSLog("hello")
         };
         b1()
         */
    }
  • 帶參數(shù)的閉包
 /**
     閉包中唇跨,參數(shù) 返回值 實(shí)現(xiàn)代碼都寫(xiě)在 {} 中
     需要使用一個(gè)關(guān)鍵字 in 來(lái)分割定義和實(shí)現(xiàn)
     */
    func demo3()  {
        // (Int) -> Int
        let b2 = { (x: Int) -> Int in
            return x
        }
        print(b2(3))

        // (Int) -> ()
        let b3 = { (x: Int) -> () in
            print("hello")
        }
        b3(3)
    }
3.Swift中GCD

與OC中的GCD使用姿勢(shì)不太一樣,但是執(zhí)行步驟是一樣的衬衬,都是先創(chuàng)建隊(duì)列买猖,然后執(zhí)行任務(wù)

  func loadData() -> () {
        // 講任務(wù)添加到隊(duì)列,指定執(zhí)行任務(wù)的函數(shù)
        /**
         OC 匯總的使用
         dispatch_async(dispatch_get_global_queue(0, 0), ^{
             dispatch_async(dispatch_get_main_queue(), ^{
             
             });
         });
         */
        
        DispatchQueue.global().async {
            print("耗時(shí)操作 \(Thread.current)")
            DispatchQueue.main.async(execute: {
                print("主線程 \(Thread.current)")
            })
        }

        // 耗時(shí)操作 <NSThread: 0x6180000646c0>{number = 3, name = (null)}
        // 主線程 <NSThread: 0x608000065380>{number = 1, name = main}
    }
4.通過(guò)閉包傳遞值
  // 閉包作為參數(shù)滋尉,閉包一般都不寫(xiě)參數(shù)名
    func loadData2(compeletion: (Int, Int) ->())  {
        compeletion(3, 4)
    }
    func loadData22(compeletion: (_ x: Int, _ y: Int) ->())  {
        compeletion(3, 4)
    }
 
   // 調(diào)用姿勢(shì)
   loadData2 { (a, b) in
        print("\(a) \(b)")
    }
   loadData22 { (a) in
        print("\(a) ")
   }

    func loadData3(compeletion: (_ array: [String]) -> ()) -> (){
        let arr: [String] = ["1", "2", "3"]
        compeletion(arr)
    }
    func loadData33(compeletion: ([String]) -> ()) {
        let arr: [String] = ["1", "2", "3"]
        compeletion(arr)
    }
      // 調(diào)用姿勢(shì)
    loadData3 { (arr) in
        print(arr)
    }

    func loadData4(x: Int, completetion: (_ array: [String]) ->()) {
        let arr: [String] = ["1", "2", "3"]
        completetion(arr)
    }
    func loadData44(x: Int, completetion: ([String]) ->()) {
        let arr: [String] = ["1", "2", "3"]
        completetion(arr)
    }
    // 調(diào)用姿勢(shì)
    loadData4(x: 3) { (array) in
         print("3 --- \(array)")
   }
5.尾隨閉包
        // 如果函數(shù)的最后一個(gè)參數(shù)是閉包玉控,函數(shù)就可以提前結(jié)束,最后一個(gè)參數(shù)直接使用{}包裝閉包的代碼
        // 省略了 compeletion 這個(gè)閉包
        loadData3 { (arr) in
            print(arr)
        }
        
        loadData3(compeletion: { (array) -> () in
            print(array)
        })
        
        loadData4(x: 3) { (array) in
            print("3 --- \(array)")
        }
6.尾隨閉包在OC上的坑

比如我們?cè)贠C中經(jīng)常寫(xiě)這樣的代碼狮惜,

    UILabel *label = [[UILabel alloc] init];
    {
        UILabel *label = [[UILabel alloc] init];
    }

在swift中尾隨閉包的問(wèn)題

  let l = UILabel()
 // 下面的這句話就會(huì)包這個(gè)錯(cuò)高诺,Extra argument in call 
// 就是由于尾隨閉包 默認(rèn)會(huì)把最后一個(gè) {} 作為尾隨閉包的結(jié)束
 view.addSubview(l)
 {
    let l = UILabel()
    view.addSubview(l)
 }
7. @escaping 的使用

如果這個(gè)閉包是在這個(gè)函數(shù)結(jié)束前內(nèi)被調(diào)用碌识,就是非逃逸的即noescape。當(dāng)一個(gè)閉包作為參數(shù)傳到一個(gè)函數(shù)中虱而,但是這個(gè)閉包在函數(shù)返回之后才被執(zhí)行筏餐,我們稱(chēng)該閉包從函數(shù)中逃逸。當(dāng)你定義接受閉包作為參數(shù)的函數(shù)時(shí)牡拇,你可以在參數(shù)名之前標(biāo)注 @escaping魁瞪,用來(lái)指明這個(gè)閉包是允許“逃逸”出這個(gè)函數(shù)的。
一種能使閉包“逃逸”出函數(shù)的方法是惠呼,將這個(gè)閉包保存在一個(gè)函數(shù)外部定義的變量中导俘。舉個(gè)例子,很多啟動(dòng)異步操作的函數(shù)接受一個(gè)閉包參數(shù)作為 completion handler剔蹋。這類(lèi)函數(shù)會(huì)在異步操作開(kāi)始之后立刻返回旅薄,但是閉包直到異步操作結(jié)束后才會(huì)被調(diào)用。在這種情況下泣崩,閉包需要“逃逸”出函數(shù)赋秀,因?yàn)殚]包需要在函數(shù)返回之后被調(diào)用。
在swift3中做出了一個(gè)對(duì)調(diào)的改變:所有的閉包都默認(rèn)為非逃逸閉包律想,不再需要@noescape猎莲;

// 如果是逃逸閉包,就用@escaping表示技即。比如下面的一段代碼著洼,callBack在從子線程切換到主線程中,
// 調(diào)用的地方超出的函數(shù)的范圍而叼,所以是逃逸閉包身笤。
    func demo4(complatetion: @escaping ([String]) -> ()) {
        DispatchQueue.global().async {
             let arr = ["1", "2" ,"3"]
             DispatchQueue.main.async(execute: {
                 complatetion(arr)
             })
        }
    }
8. Swift閉包中$0 和 $1的理解

Swift 自動(dòng)對(duì)行內(nèi)閉包提供簡(jiǎn)寫(xiě)實(shí)際參數(shù)名,你也可以通過(guò) $0 , $1 , $2 等名字來(lái)引用閉包的實(shí)際參數(shù)值葵陵。
如果你在閉包表達(dá)式中使用這些簡(jiǎn)寫(xiě)實(shí)際參數(shù)名液荸,那么你可以在閉包的實(shí)際參數(shù)列表中忽略對(duì)其的定義,并且簡(jiǎn)寫(xiě)實(shí)際參數(shù)名的數(shù)字和類(lèi)型將會(huì)從期望的函數(shù)類(lèi)型中推斷出來(lái)脱篙。 in 關(guān)鍵字也能被省略娇钱,因?yàn)殚]包表達(dá)式完全由它的函數(shù)體組成,舉個(gè)栗子:

let numbers = [3,2,4,1,5,7,6];

var sortedNumbers = numbers.sorted(by:{$0 < $1});
print(sortedNumbers);//輸出為:[1, 2, 3, 4, 5, 6, 7]
 
sortedNumbers = numbers.sorted(by:{$1 < $0});
print(sortedNumbers);//輸出為:[7, 6, 5, 4, 3, 2, 1]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绊困,隨后出現(xiàn)的幾起案子文搂,更是在濱河造成了極大的恐慌,老刑警劉巖秤朗,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煤蹭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)硝皂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)常挚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人稽物,你說(shuō)我怎么就攤上這事待侵。” “怎么了姨裸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵秧倾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我傀缩,道長(zhǎng)那先,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任赡艰,我火速辦了婚禮售淡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘慷垮。我一直安慰自己揖闸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布料身。 她就那樣靜靜地躺著汤纸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芹血。 梳的紋絲不亂的頭發(fā)上贮泞,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音幔烛,去河邊找鬼啃擦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饿悬,可吹牛的內(nèi)容都是我干的令蛉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼狡恬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼珠叔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起傲宜,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤运杭,失蹤者是張志新(化名)和其女友劉穎夫啊,沒(méi)想到半個(gè)月后函卒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年报嵌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虱咧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锚国,死狀恐怖腕巡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情血筑,我是刑警寧澤绘沉,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站豺总,受9級(jí)特大地震影響车伞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喻喳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一另玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧表伦,春花似錦谦去、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至纲熏,卻和暖如春窃诉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赤套。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工飘痛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人容握。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓宣脉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親剔氏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子塑猖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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