欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Swift中的函數(shù)及函數(shù)閉包使用

 更新時(shí)間:2016年06月24日 15:21:10   作者:琿少  
Swift的函數(shù)在創(chuàng)建和調(diào)用時(shí)非常簡(jiǎn)潔,在編寫(xiě)具有閉包特性的函數(shù)時(shí)同樣也相當(dāng)方便,以下我們就來(lái)詳解Swift中的函數(shù)及函數(shù)閉包使用:

一、引言

函數(shù)是有特定功能的代碼段,函數(shù)會(huì)有一個(gè)特定的名稱調(diào)用時(shí)來(lái)使用。Swift提供了十分靈活的方式來(lái)創(chuàng)建與調(diào)用函數(shù)。事實(shí)上在Swift,每個(gè)函數(shù)都是一種類型,這種類型由參數(shù)和返回值來(lái)決定。Swift和Objective-C的一大區(qū)別就在于Swift中的函數(shù)可以進(jìn)行嵌套。

而Swift中的閉包是有一定功能的代碼塊,這十分類似于Objective-C中的block語(yǔ)法。Swift中的閉包語(yǔ)法風(fēng)格十分簡(jiǎn)潔,其作用和函數(shù)的作用相似。

二、函數(shù)的創(chuàng)建與調(diào)用

函數(shù)通過(guò)函數(shù)名,參數(shù)和返回值來(lái)定義,參數(shù)和返回值決定一個(gè)函數(shù)的類型,在調(diào)用函數(shù)時(shí),使用函數(shù)名來(lái)進(jìn)行調(diào)用,示例如下:

//傳入一個(gè)名字 打印并將其返回
func printName(name:String) -> String {
  print(name)
  return name
}
//進(jìn)行函數(shù)的調(diào)用
printName("HS")

也可以創(chuàng)建沒(méi)有參數(shù)的函數(shù):

func onePuseTwo()->Int {
  return 1+2
}
onePuseTwo()
同樣也可以創(chuàng)建沒(méi)有返回值的函數(shù):

func sayHello(){
  print("Hello")
}
sayHello()

上面介紹的函數(shù)類型都比較常見(jiàn),對(duì)于多返回值的函數(shù),在Objective-C中十分難處理,開(kāi)發(fā)者通常會(huì)采用字典、數(shù)組等集合方式或者干脆使用block回調(diào),在Swift中,可以使用元組作為函數(shù)的返回值,示例如下:

func tuples()->(Int,String){
  return (1,"1")
}
tuples()

也可以是函數(shù)返回一個(gè)Optional類型的值,支持返回nil,示例如下:

func func1(param:Int)->Int? {
  guard(param>0)else{
    return nil
  }
  return param
}
func1(0)
func1(1)

在函數(shù)的參數(shù)名前,開(kāi)發(fā)者還可以再為其添加一個(gè)參數(shù)名稱作為外部參數(shù)名,示例如下:

func func1(count param:Int ,count2 param2:Int)->Int? {
  //內(nèi)部依然使用param
  guard(param>0)else{
    return nil
  }
  return param
}
//外部調(diào)用使用count
func1(count: 0,count2: 0)
func1(count: 1,count2: 1)

其實(shí)Swift函數(shù)中的參數(shù)列表有這樣一個(gè)特點(diǎn),除了第一個(gè)參數(shù)外,之后的參數(shù)都默認(rèn)添加一個(gè)一個(gè)和內(nèi)部名稱相同的外部名稱,如果開(kāi)發(fā)者不想使用這個(gè)外部名稱,使用_符號(hào)設(shè)置,示例如下:

func func2(param:Int,param2:Int,param3:Int) {
  
}
//有外部名稱
func2(0, param2: 0, param3: 0)
func func3(param:Int,_ param2:Int,_ param3:Int) {
  
}
//沒(méi)有外部名稱
func3(0, 0, 0)

Swift也支持開(kāi)發(fā)者為函數(shù)的參數(shù)創(chuàng)建一個(gè)默認(rèn)值,如果函數(shù)的某個(gè)參數(shù)有設(shè)置默認(rèn)值,則開(kāi)發(fā)者在調(diào)用時(shí)可以省略此參數(shù),示例如下:

func func4(param:Int=1,param2:Int=2,param3:Int) {
  print(param,param2,param3)
}
func4(3,param3:3)

還有一種情形在Objective-C中也很處理,對(duì)于參數(shù)數(shù)量不定的函數(shù),在前面章節(jié)介紹過(guò),Objective-C一般會(huì)使用list指針來(lái)完成,在Swift中編寫(xiě)這樣的函數(shù)十分簡(jiǎn)單,示例如下:

func func5(param:Int...) {
  for index in param {
    print(index)
  }
}
func5(1,2,3,4)

Swift中參數(shù)默認(rèn)是常量,在函數(shù)中是不能修改外部傳入?yún)?shù)的值得,如果有需求,需要將參數(shù)聲明成inout類型,示例如下:

func func6(inout param:Int) {
  param = 10
}
var count = 1
//實(shí)際上傳入的是參數(shù)地址
func6(&count)
print(count)

三、函數(shù)類型

函數(shù)是一種特殊的數(shù)據(jù)類型,每一個(gè)函數(shù)屬于一種數(shù)據(jù)類型,示例如下:

func func7(a:Int,_ b:Int)->Int{
  return a+b
}
var addFunc:(Int,Int)->Int = func7
addFunc(1,2)

函數(shù)也可以作為參數(shù)傳入另一個(gè)函數(shù),這十分類似于Objective-C中的block語(yǔ)法,示例如下:

func func7(a:Int,_ b:Int)->Int{
  return a+b
}
var addFunc:(Int,Int)->Int = func7
addFunc(1,2)
func func8(param:Int,param2:Int,param3:(Int,Int)->Int) -> Int {
  return param3(param,param2)
}
//傳入函數(shù)
func8(1, param2: 2, param3: addFunc)
//閉包的方式
func8(2, param2: 2, param3:{ (a:Int,b:Int) -> Int in
  return a*b
  })

一個(gè)人函數(shù)也可以作為另一個(gè)函數(shù)的返回值,示例如下:

func func9()->(Int)->Int{
  //Swift支持嵌套函數(shù)
  func tmp(a:Int)->Int{
    return a*a
  }
  return tmp
}
var myFunc = func9()
myFunc(3)

四、從一個(gè)系統(tǒng)函數(shù)看閉包

Swift標(biāo)準(zhǔn)函數(shù)庫(kù)中提供了一個(gè)sort排序函數(shù),對(duì)于已經(jīng)元素類型的數(shù)組,調(diào)用sort函數(shù)會(huì)進(jìn)行重新排序并返回新的排序后的數(shù)組。這個(gè)sort函數(shù)可以接收一個(gè)返回值為Bool類型的閉包,來(lái)確定第一個(gè)元素是否排在第二個(gè)元素前面。代碼示例如下:

var array = [3,21,5,2,64]
func func1(param1:Int,param2:Int) -> Bool {
  return param1>param2
}
//通過(guò)傳入函數(shù)的方式
//array = [64,21,5,3,2]
array = array.sort(func1)
//通過(guò)閉包的方式
//array = [2,3,5,21,64]
array = array.sort({(param:Int,param2:Int)->Bool in
            return param<param2
          })

Swift語(yǔ)言有一個(gè)很顯著的特點(diǎn)就是簡(jiǎn)潔,可以通過(guò)上下文推斷出類型的情況一般開(kāi)發(fā)都可以將類型的書(shū)寫(xiě)省略,這也是Swift語(yǔ)言設(shè)計(jì)的一個(gè)思路,由于閉包是作為函數(shù)的參數(shù)傳入函數(shù)中的,因?yàn)楹瘮?shù)參數(shù)的類型是確定,因此閉包的類型是可以被編譯器推斷出來(lái)的,開(kāi)發(fā)者也可以將閉包的參數(shù)類型和返回值省略,上面的代碼可以簡(jiǎn)寫(xiě)如下:

//將閉包的參數(shù)類型和返回值都省略
array = array.sort({(p1,p2) in return p1>p2})

實(shí)際上,如果閉包中的函數(shù)體只有一行代碼,可以將return關(guān)鍵字也省略,這時(shí)會(huì)隱式的返回此行代碼的值,如下:

array = array.sort({(p1,p2) in  p1>p2})

看到上面的表達(dá)式,是不是有點(diǎn)小震驚,閉包表達(dá)式竟然可以簡(jiǎn)寫(xiě)成這樣!然而,你還是小看的Swift開(kāi)發(fā)團(tuán)隊(duì),后面的語(yǔ)法規(guī)則會(huì)讓你明白什么是簡(jiǎn)潔的極致??梢钥吹缴厦娴拇a實(shí)現(xiàn)還是有3部分:參數(shù)和返回值,閉包關(guān)鍵字,函數(shù)體。參數(shù)和返回值即是參數(shù)列表,p1,p2,雖然省略了參數(shù)類型和返回值類型,但這部分的模塊還在,閉包關(guān)鍵字即是in,它用來(lái)表示下面將是閉包的函數(shù)體,p1>p2即是函數(shù)體,只是這里省略了return關(guān)鍵字。閉包中既然參數(shù)類型和返回值類型編譯器都可以自己推斷出來(lái),那么參數(shù)的數(shù)量編輯器也是可以自行推斷的,因此,參數(shù)列表實(shí)際上也是多余的,閉包中會(huì)自動(dòng)生成一些參數(shù)名稱,和實(shí)際的參數(shù)數(shù)量向?qū)?yīng),例如上面sort函數(shù)中的閉包有兩個(gè)參數(shù),系統(tǒng)會(huì)自動(dòng)生成$0和$1這兩個(gè)參數(shù)名,開(kāi)發(fā)者可以直接使用,因?yàn)閰?shù)列表都會(huì)省略了,那么也不再需要閉包關(guān)鍵字in來(lái)分隔參數(shù)列表與函數(shù)體,這時(shí),閉包的寫(xiě)法實(shí)際上變成了如下的模樣:

array = array.sort({$0<$1})

你沒(méi)有看錯(cuò),加上左右的大括號(hào),一共7個(gè)字符,完成了一個(gè)排序算法。除了Swift,我不知道是否還有第二種語(yǔ)言可以做到。拋開(kāi)閉包不說(shuō),Swift中還有一種語(yǔ)法,其可以定義類型的運(yùn)算符方法,例如String類型可以通過(guò)=,<,>來(lái)進(jìn)行比較,實(shí)際上是String類中實(shí)現(xiàn)了這些運(yùn)算符方法,在某種意義上說(shuō),一個(gè)運(yùn)算符即類似與一個(gè)函數(shù),那么好了,sort函數(shù)中需要傳入的方法對(duì)于某些類型來(lái)說(shuō)實(shí)際上只是需要一個(gè)運(yùn)算符,示例如下:

array = array.sort(>)

這次你可以真的震驚了,完成排序新算法只需要一個(gè)字符,不折不扣的一個(gè)字符。

五、Swift中閉包的更多特點(diǎn)

Swift中的閉包還有一個(gè)有趣的特點(diǎn),首先閉包是作為參數(shù)傳入另一個(gè)函數(shù)中的,因此常規(guī)的寫(xiě)法是將閉包的大括號(hào)寫(xiě)在函數(shù)的參數(shù)列表小括號(hào)中,如果閉包中的代碼很多,這時(shí)在代碼結(jié)構(gòu)上來(lái)看會(huì)變得并不太清晰,為了解決這個(gè)問(wèn)題,Swift中這樣規(guī)定:如果這個(gè)閉包參數(shù)是函數(shù)的最后一個(gè)參數(shù),開(kāi)發(fā)者可以將其拉出小括號(hào),在函數(shù)尾部實(shí)現(xiàn)閉包代碼,示例如下:

//閉包結(jié)尾
func func2(param1:Int,param2:()->Void)->Void{
  param2()
  print("調(diào)用了func2函數(shù)")
}
func2(0){
    print("閉包中的內(nèi)容")
}

如果一個(gè)函數(shù)中只有一個(gè)參數(shù),且這個(gè)參數(shù)是一個(gè)閉包,那么開(kāi)發(fā)者使用閉包結(jié)尾這種寫(xiě)法,完全可以將函數(shù)的參數(shù)列表小括號(hào)也省略掉,示例如下:

func func3(param:()->Void)->Void{
  param()
  print("調(diào)用了func3函數(shù)")
}
func3{
  print("閉包中的內(nèi)容")
}

Swift中還有一個(gè)閉包逃逸的概念,這個(gè)很好理解,當(dāng)閉包作為參數(shù)傳遞進(jìn)函數(shù)時(shí),如果這個(gè)閉包只在函數(shù)中被使用,則開(kāi)發(fā)者可以將這個(gè)閉包聲明成非逃逸的,即告訴系統(tǒng)當(dāng)此函數(shù)結(jié)束后,這個(gè)閉包的聲明周期也將結(jié)束,這樣做的好處是可以提高代碼性能,將閉包聲明稱非逃逸的類型使用@noescape關(guān)鍵字,示例如下:

func func3(@noescape param:()->Void)->Void{
  param()
  print("調(diào)用了func3函數(shù)")
}
func3{
  print("閉包中的內(nèi)容")
}

逃逸的閉包常用于異步的操作,例如這個(gè)閉包是異步處理一個(gè)網(wǎng)絡(luò)請(qǐng)求,只有當(dāng)請(qǐng)求結(jié)束后,閉包的聲明周期才結(jié)束。非逃逸的閉包還有一個(gè)有趣的特點(diǎn),在其內(nèi)部如果需要使用self這個(gè)關(guān)鍵字,self可以被省略。

閉包也可以被自動(dòng)的生成,這種閉包被稱為自動(dòng)閉包,自動(dòng)閉包可以自動(dòng)將表達(dá)式封裝成閉包,開(kāi)發(fā)者不需要再寫(xiě)閉包的大括號(hào)格式,自動(dòng)閉包不接收參數(shù),返回值為其中表達(dá)式的值。示例如下:

//自動(dòng)閉包演示
var list = [1,2,3,4,5,6]
//創(chuàng)建一個(gè)顯式閉包
let closures = {
  list.removeFirst()
  list.append(7)
}
//將打印[1,2,3,4,5,6]
print(list)
//執(zhí)行閉包
closures()
//將打印[2,3,4,5,6,7]
print(list)
func func4(closure:()->Void) -> Void {
  //執(zhí)行顯式的閉包
  closures()
}
func func5(@autoclosure auto:()->Void) -> Void {
  //執(zhí)行自動(dòng)閉包
  auto()
}
//顯式閉包 需要大括號(hào)
func4(closures)
//將打印[3,4,5,6,7,7]
print(list)
//將表達(dá)式自動(dòng)生成閉包
func5(list.append(8))
//將打印[3,4,5,6,7,7,8]
print(list)

自動(dòng)閉包默認(rèn)是非逃逸的,如果要使用逃逸的閉包,需要手動(dòng)聲明,如下:

func func5(@autoclosure(escaping) auto:()->Void) -> Void {
  //執(zhí)行自動(dòng)閉包
  auto()
}

相關(guān)文章

  • Swift 3.0基礎(chǔ)學(xué)習(xí)之類與結(jié)構(gòu)體

    Swift 3.0基礎(chǔ)學(xué)習(xí)之類與結(jié)構(gòu)體

    最近在學(xué)swift 3.0,主要看的是蘋(píng)果的官方文檔,這里只是根據(jù)自己看官方文檔的理解所做的一些記錄,不是完整的翻譯,希望也對(duì)你有所幫助。下面這篇文章主要介紹了Swift 3.0基礎(chǔ)學(xué)習(xí)之類與結(jié)構(gòu)體的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-03-03
  • Ubuntu 16.04上安裝 Swift 3.0及問(wèn)題解答

    Ubuntu 16.04上安裝 Swift 3.0及問(wèn)題解答

    本文給大家分享的是在Ubuntu系統(tǒng)中安裝 Swift 3.0的方法和步驟,以及安裝過(guò)程中有可能遇到的問(wèn)題的解答,這里推薦給小伙伴們,希望大家能夠喜歡
    2016-07-07
  • 如何刪掉編程中的?Switch?語(yǔ)句

    如何刪掉編程中的?Switch?語(yǔ)句

    多重方法是一種有趣的方式,可以幫你擺脫令人討厭的?switch,這篇文章主要介紹了如何刪掉編程中的?Switch?語(yǔ)句,需要的朋友可以參考下
    2022-09-09
  • 深入講解Swift中的模式匹配

    深入講解Swift中的模式匹配

    在Swift中,一些模式已經(jīng)被語(yǔ)言特性所吸收,你在使用Swift甚至察覺(jué)不出這類問(wèn)題的存在,下面這篇文章主要給大家介紹了關(guān)于Swift中模式匹配的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • Swift?中?Opaque?Types學(xué)習(xí)指南

    Swift?中?Opaque?Types學(xué)習(xí)指南

    這篇文章主要為大家介紹了Swift?中?Opaque?Types學(xué)習(xí)指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 詳解Swift的內(nèi)存管理

    詳解Swift的內(nèi)存管理

    這篇文章主要介紹了Swift的內(nèi)存管理,對(duì)內(nèi)存管理感興趣的同學(xué),可以參考下
    2021-04-04
  • 利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)

    利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)

    最近在學(xué)習(xí)swift,最近有空所以總結(jié)一下最近學(xué)習(xí)的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-12-12
  • 深入解析Swift中switch語(yǔ)句對(duì)case的數(shù)據(jù)類型匹配的支持

    深入解析Swift中switch語(yǔ)句對(duì)case的數(shù)據(jù)類型匹配的支持

    這篇文章主要介紹了Swift中switch語(yǔ)句對(duì)case的數(shù)據(jù)類型匹配的支持,Swift中switch...case語(yǔ)句支持多種數(shù)據(jù)類型的匹配判斷,十分強(qiáng)大,需要的朋友可以參考下
    2016-04-04
  • Swift中定義二維數(shù)組的方法及遍歷方法示例

    Swift中定義二維數(shù)組的方法及遍歷方法示例

    這篇文章主要介紹了Swift中定義二維數(shù)組的方法及遍歷方法示例,本文直接給出代碼示例,需要的朋友可以參考下
    2015-07-07
  • Objective-c代碼如何移植為Swift代碼 Objective-c代碼轉(zhuǎn)移到Swift過(guò)程介紹

    Objective-c代碼如何移植為Swift代碼 Objective-c代碼轉(zhuǎn)移到Swift過(guò)程介紹

    這篇文章主要介紹了Objective-c代碼如何移植為Swift代碼,Objective-c代碼轉(zhuǎn)移到Swift過(guò)程介紹,需要的朋友可以參考下
    2014-07-07

最新評(píng)論