Swift-閉包

【返回目錄】



一、閉包表達式(Closure Expression)

在Swift中,可以通過func閉包表達式 定義一個函數(shù)
相當于Objective-C語言中 Block


  • func函數(shù)
func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }


  • 閉包表達式
{
    (參數(shù)列表) -> 返回值類型 in 
    函數(shù)體代碼
}
var fn =  {
    (v1: Int, v2: Int) -> Int in
    return v1 + v2
}
fn(10, 20)
{
    (v1: Int, v2: Int) -> Int in
    return v1 + v2
}(10, 20)


  • 閉包表達式的簡寫
func exec(v1: Int, v2: Int, fn:(Int, Int) -> Int) {
    print(fn(v1, v2))
}

調(diào)用簡寫

exec(v1: 10, v2: 20, fn: { (v1: Int, v2: Int) in
    return v1 + v2
})
exec(v1: 10, v2: 20, fn: { v1, v2 in
    return v1 + v2
})
exec(v1: 10, v2: 20, fn: { v1, v2 in
    v1 + v2
})
exec(v1: 10, v2: 20, fn: {
    $0 + $1
})
exec(v1: 10, v2: 20, fn: +)


  • 尾隨閉包

1.如果將一個很長的閉包表達式作為函數(shù)的最后一個參數(shù),使用尾隨閉包可以增強函數(shù)的可讀性;尾隨閉包是一個被書寫在函數(shù)調(diào)用括號外面(后面)的閉包表達式;

exec(v1: 10, v2: 20) { v1, v2 in
    v1 + v2
}
exec(v1: 10, v2: 20) {
    $0 + $1
}

2.如果閉包表達式是函數(shù)的唯一實參,而且使用了尾隨閉包的語法,那就不需要在函數(shù)后面寫圓括號

func exec(fn:(Int, Int) -> Int) {
    print(fn(10, 20))
}

調(diào)用尾隨閉包

exec(fn: { 
    $0 + $1 
})

exec() { v1, v2 in
     v1 + v2 
}

exec{ v1, v2 in 
    v1 + v2
}

exec { $0 + $1 }




  • 示例·數(shù)組排序

從小到大排序

var nums = [10, 7, 4, 8, 1, 5, 3, 6, 2, 0, 9]
nums.sort()
print(nums) //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


使用函數(shù)

func cmp(i1: Int, i2: Int) -> Bool {
    //大的排在前面
    // 返回true:i1排在i2前面; false:i1排在i2后面
    return i1 > i2
}
nums.sort(by: cmp)
print(nums)//[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]


使用閉包表達式

nums.sort(by: { (i1: Int, i2: Int) -> Bool in
    return i1 < i2
})
nums.sort(by: { i1, i2 in
    return i1 < i2
})
nums.sort(by: { $0 < $1 })
nums.sort(by: < )
//尾隨閉包簡寫
nums.sort(){ $0 < $1 }
nums.sort { $0 < $1 }


  • 忽略實參
func exec(fn:(Int, Int) -> Int) {
    print(fn(10, 20))
}
exec { _ ,_ in
    return 10
}





二、閉包(Closure)

  • 定義
    1.一個函數(shù)和他所捕獲的變量/常量環(huán)境組合起來,稱為“閉包
    2.一般指定義在函數(shù)內(nèi)部的函數(shù)
    3.一般它捕獲的是外層函數(shù)的局部變量/常量
typealias Fn = (Int) -> Int

func getFn() -> Fn {
    //局部變量
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num
    }
    //返回的plus和num形成了閉包
    return plus
}
var fn = getFn()
print(fn(1))
// 1、3、6、10


  • 可以把閉包想象成某個類的實例對象
    1.內(nèi)存在堆空間
    2.捕獲的局部變量/常量就是對象的成員(存儲屬性)
    3.組成閉包的函數(shù)就是類內(nèi)部定義的方法
class Closure {
    var num = 0
    func plus(_ i: Int) -> Int {
        num += i
        return num
    }
}
var cs = Closure()
print("Class ",cs.plus(1))
print("Class ",cs.plus(2))


  • 示例1 - 對應關系
typealias Fn = (Int) -> (Int, Int)

func getFns() -> (Fn, Fn) {
    var num1 = 0
    var num2 = 0

    func plus(_ i: Int) -> (Int, Int) {
        num1 += i
        num2 += i << 1
        return (num1, num2)
    }

    func minus(_ i: Int) -> (Int, Int) {
        num1 -= i
        num2 -= i << 1
        return (num1, num2)
    }

    return (plus, minus)
}
let (p, m) = getFns()
p(5) //(5, 10)
m(4) //(1, 2)
class Closure {
    var num1 = 0
    var num2 = 0

    func plus(_ i: Int) -> (Int, Int) {
        num1 += i
        num2 += i << 1
        return (num1, num2)
    }

    func minus(_ i: Int) -> (Int, Int) {
        num1 -= i
        num2 -= i << 1
        return (num1, num2)
    }
}
var cs = Closure()
cs.plus(5)
cs.minus(4)


  • 示例2 - 對應關系
var functions: [() -> Int] = []

for i in 1...3 {
    functions.append {
        return i
    }
} // [(Function), (Function), (Function)]

for f in functions {
    print("-->",f())
}
class Closure {
    var i: Int
    init(_ i: Int) {
        self.i = i
        print("-------- \(i)")
    }
    func getFn() -> Int {
        return i
    }
}

var clses : [Closure] = []

for i in 1...3 {
    let c = Closure(i)
    clses.append(c)
}

for cls in clses {
    print(cls.getFn())
}


  • 注意
    如果返回值是函數(shù)類型,那么參數(shù)的修飾要保持統(tǒng)一
func add(_ num: Int) -> (inout Int) -> Void {
    func plus(v: inout Int) {
        v += num
    }
    return plus
}
var num = 5
add(20)(&num)
print("num:",num)





三、自動閉包(Automatic Closure)

  • @autoclosure 會自動將20封裝成閉包{ 20 }
  • @autoclosure 只支持() -> T格式的參數(shù)
  • @autoclosure 并非只支持最后1個參數(shù)
  • 空合并運算符?? 使用了 @autoclosure 技術
  • @autoclosure、無@autoclosure構(gòu)成了函數(shù)重載


1.如果第一個數(shù)大于0,返回第一個數(shù),否則返回第二個數(shù)。

func getFirstPositive(_ v1: Int, _ v2:Int) -> Int {
    return v1 > 0 ? v1 : v2
}
getFirstPositive(10, 20)
getFirstPositive(-2, 20)


2.改成函數(shù)類型的參數(shù),可以讓v2延遲加載

func getFirstPositive(_ v1: Int, _ v2: () -> Int) -> Int? {
    return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4) { 20 }


3.@autoclosure

//為了避免與期望沖突,使用了`@autoclosure`的地方最好明確注釋清楚這個值會被推遲執(zhí)行
func getFirstPositive(_ v1: Int, _ v2:@autoclosure () -> Int) -> Int? {
    return v1 > 0 ? v1 : v2()
}
getFirstPositive(-4, 20) //將20封裝成閉包{ 20 }







【上一篇】:類
【下一篇】:屬性



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 閉包可以從定義它們的上下文中捕獲和存儲對任何常量和變量的引用。 這被稱為關閉這些常量和變量。 Swift處理所有的...
    Joker_King閱讀 638評論 0 2
  • 閉包 閉包可以捕獲和存儲其所在上下文中任意常量和變量的引用,被稱為包裹常量和變量。Swift 會為你管理在捕獲過程...
    DevXue閱讀 258評論 0 0
  • 先復習一下函數(shù)Swift-func[http://www.itdecent.cn/p/38c830d98561]...
    守護地中海的花閱讀 1,117評論 0 3
  • Swift-閉包 Swift閉包的含義 閉包是自包含的功能代碼塊,可以用作函數(shù)的參數(shù)或者返回值 閉包可以捕獲上下文...
    stackJolin閱讀 1,296評論 0 2
  • 閉包表達式 在swift中,可以通過func定義一個函數(shù),也可以通過閉包表達式定義一個函數(shù) 閉包表達式簡寫 尾隨閉...
    XTK_iOS閱讀 467評論 0 3

友情鏈接更多精彩內(nèi)容