Swift-閉包

/* 閉包(Closures) 
 * 閉包是自包含的功能代碼塊,能夠在代碼中使用或者用來做爲參數傳值。 
 * 在Swift中的閉包與C、OC中的blocks和其它編程語言(如Python)中的lambdas相似。 
 * 閉包能夠捕獲和存儲上下文中定義的的任何常量和變量的引用。這就是所謂的變量和變量的自封閉, 
 * 所以命名爲」閉包「("Closures)").Swift還會處理全部捕獲的引用的內存管理。 
 *  
 * 全局函數和嵌套函數其實就是特殊的閉包。 
 * 閉包的形式有: 
 * (1)全局函數都是閉包,有名字但不能捕獲任何值。 
 * (2)嵌套函數都是閉包,且有名字,也能捕獲封閉函數內的值。 
 * (3)閉包表達式都是無名閉包,使用輕量級語法,能夠根據上下文環境捕獲值。 
 *  
 * Swift中的閉包有不少優化的地方: 
 * (1)根據上下文推斷參數和返回值類型 
 * (2)從單行表達式閉包中隱式返回(也就是閉包體只有一行代碼,能夠省略return) 
 * (3)能夠使用簡化參數名,如$0, $1(從0開始,表示第i個參數...) 
 * (4)提供了尾隨閉包語法(Trailing closure syntax) 
 */  
   
 // 下面用Swift標準庫中的sort方法來一步步簡化閉包寫法  
 // sort函數須要兩個參數  
 // 參數一:數組  
 // 參數二:一個閉包:帶有兩個參數,這兩個參數類型與數組中的元素類型相同,返回值是Bool  
 var names = ["Swift", "Arial", "Soga", "Donary"]  
   
 // 第一種方式:使用函數  
 func backwards(firstString: String, secondString: String) -> Bool {  
   return firstString > secondString // 升序排序  
 }  
 // 這裏第二個參數,傳了一個函數  
 // reversed is equal to ["Swift", "Soga", "Donary", "Arial"]  
 var reversed = sort(nams, backwards)  
   
 // 第二種方式:使用閉包方式  
 // 完整閉包寫法是在花括號內有參數列表和返回值,用關鍵字in代表閉包體的開始  
 // (firstString: String, secondString: String) 閉包參數列表  
 // -> Bool 指明閉包返回值類型是Bool  
 // in關鍵字代表閉包體的開始  
 reversed = sort(names, { (firstString: String, secondString: String) -> Bool in  
    return firstString > secondString  
    })  
  
 // 這裏能夠進一步簡化寫法,由於閉包代碼比較短,能夠寫到一行上  
 reversed = sort(names, { (firstString: String, secondString: String) -> Bool in return firstString > secondString})  
   
// 下面再進一步簡化寫法 :根據環境上下文自動推斷出類型  
// 參數列表都沒有指明類型,也沒有指明返回值類型,這是由於swift能夠根據上下文推測出  
// firstString和secondString的類型會是names數組元素的類型,而返回值類型會根據return語句結果獲得  
reversed = sort(names, { firstString, secondString in return firstString > secondString})  
  
// 再進一步簡化:隱式返回(單行語句閉包)  
// 由於閉包體只有一行代碼,能夠省略return  
reversed = sort(names, { firstString, secondString in firstString > secondString})  
  
// 再進一步簡化:使用簡化參數名($i,i=0,1,2...從0開始的)  
// Swift會推斷出閉包須要兩個參數,類型與names數組元素相同  
reversed = sort(names, { $0 > $1 })    
  
// 最簡單的一種寫法:使用操做符  
reversed = sort(names, >)      
      
      
/* 
 * 尾隨閉包(Trailing Closures) 
 * 若是函數須要一個閉包參數做爲參數,且這個參數是最後一個參數,而這個閉包表達式又很長時, 
 * 使用尾隨閉包是頗有用的。尾隨閉包能夠放在函數參數列表外,也就是括號外。若是函數只有一個參數, 
 * 那麼能夠把括號()省略掉,後面直接跟着閉包。 
 */   
// Array的方法map()就須要一個閉包做爲參數  
let strings = numbers.map { // map函數後面的()能夠省略掉  
  (var number) -> String in  
  var output = ""  
  while number > 0 {  
    output = String(number % 10) + output   
    number /= 10  
  }  
  return output  
}  
      
/* 捕獲值 
 * 閉包能夠根據環境上下文捕獲到定義的常量和變量。閉包能夠引用和修改這些捕獲到的常量和變量, 
 * 就算在原來的範圍內定義爲常量或者變量已經再也不存在(很牛逼)。 
 * 在Swift中閉包的最簡單形式是嵌套函數。 
 */   
func increment(#amount: Int) -> (() -> Int) {  
  var total = 0  
  func incrementAmount() -> Int {  
    total += amount // total是外部函數體內的變量,這裏是能夠捕獲到的  
    return total  
  }  
  return incrementAmount // 返回的是一個嵌套函數(閉包)  
}     
      
// 閉包是引用類型,因此incrementByTen聲明爲常量也能夠修改total  
let incrementByTen = increment(amount: 10)   
incrementByTen() // return 10,incrementByTen是一個閉包  
// 這裏是沒有改變對increment的引用,因此會保存以前的值  
incrementByTen() // return 20     
incrementByTen() // return 30     
  
let incrementByOne = increment(amount: 1)  
incrementByOne() // return 1  
incrementByOne() // return 2      
incrementByTen() // return 40   
incrementByOne() // return 3  
     
相關文章
相關標籤/搜索