Cowboy Tech

Swift中的函数和闭包

函数

函数的种类和声明

Global Functions

在文件中的任何地方都可以调用,比如:

print("I'm a global function!")

Method

在某个class里声明,需要用对象来调用,比如

let array = ["A", "13", "B","5","87", "t", "41"]

class Arithmetic {
func sumOfStrings(aBunchOfStrings: [String]) -> Int {
    let array = aBunchOfStrings
    var sum = 0
    for string in array {
        if Int(string) != nil {
            let intToAdd = Int(string)!
            sum += intToAdd
        }
    }
    return sum
}
}

函数的声明

func functionName (parameterName: parameterType) -> returnType {
    statements to execute
    return object
 }

外部参数名

func functionName (externalParameterName localParameterName: parameterType) -> returnType {
    statements to execute
    return object
 }

比如

func area (宽 width:Double ,高 height:Double ) ->Double {

return width * height
}

print (area(宽:3.4,高:4.7)) //宽和高为外部函数名

函数的参数

数组参数

func sum(numbers:Int...)->Int {
var total: Int = 0
for num in numbers {
   total += num
}
print(total)
return total
}
sum(1,3,4,5)
  1. 在参数类型后面添加…表示该参数可以接受多个参数值
  2. 一个函数当中只有一个数组参数,并且位于列表的最后

默认参数

1
2
3
4
5
 func sayHi(msg:String, name:String="Lily"){
print ("\(name),\(msg)")
}
sayHi("Welcome to our city") //目前只传入了一个参数,如果第二个参数没传入,就使用默认值
sayHi("Welcome to our city", name:"Tom") //如果传入了,就使用传入的新值

忽略形参名,添加下划线 _

1
2
3
4
func sayHi(msg:String, _name:String="Lily"){ 
print ("\(name),\(msg)")
}
sayHi("Welcome to our city","Tom")

如果函数里有可变参数也有默认参数,数组参数放在最后面,默认参数出现在次后面

变量形参

因为传入的参数是常量,如果需要在函数内进行变动数据的话,需要先设个变量 (swift 3)

func placeFirstLetterLast(myString: String) -> String {

var newString = myString
newString.append(firstCharacterOf(word: myString))
newString.removeAtIndex(myString.startIndex)
return newString
}

placeFirstLetterLast("Mom")

swift2的解决办法。swift3将取消

//这里的形参是个变量,如果去掉var就是个常量,因为形参默认是常量constant
func factorial(var number:Int) -> Int{
var result:Int = 1
while number > 1 {
    result = result * number
    number -= 1
}
return result
}
print(factorial(3))

In-out形参

func swap (inout a:Int, inout b:Int){
let tmp = a
a = b
b = tmp
}

var a:Int = 1
var b:Int = 3
swap(&a,&b)
print("交换之后的结构为:a=\(a),b=\(b)")
  1. In-out参数就是强制传递变量的指针,因为在swift里,大多是值类型,而不是指针类型
  2. 只能传入变量作为实参
  3. 输入输出不能带有默认值
  4. 如果你用关键字inout标记了一个参数,这个参数不能再用var或者let去标记

函数返回值

void

没有指定返回类型的函数总返回void,在swift中,void可以理解为空元组

func sayHi2(){
print("welcome")
}
sayHi2()

多个返回值

func area(width:Double,height:Double)->(Double,Double){
let s = width * height
let c = (width + height) * 2
return (s,c)
}
print(area(3.1, height: 3.4))

函数使用

函数作为变量

func addTwoInts(a:Int,b:Int)->Int{
return a+b
}

func multiplyTwoInts(a:Int,b:Int)->Int{ 
return a*b
}

var mathFunction:(Int,Int) -> Int = multiplyTwoInts
print("Result:\(mathFunction(2,3))")

函数作为参数

func addTwoInts(a:Int,b:Int)->Int{
return a+b
}

func multiplyTwoInts(a:Int,b:Int)->Int{
return a*b
}

func printMathResult(mathFunction:(Int,Int)->Int,a:Int,b:Int){
print("Result:\(mathFunction(a,b))")
}

printMathResult(addTwoInts,a: 3,b: 5)

函数类型作为返回值类型

func squre(num:Int) ->Int{
return num * num
}

func cube(num:Int) ->Int{
return num * num * num
}

func getMathFunc (jack: String)-> (Int)->Int {

switch (jack){
case "squre":
    return squre
default:
    return cube
}
}

var mathFunc = getMathFunc("other") // 返回的值是需要传入整数的函数
print(mathFunc(5)) //所以这里传入整数

函数重载

形参和返回值不一样的同名函数

//1.
func test(){
print("无参数的test()函数")
}

//2.
func test (msg: String){
print("重载的test()函数\(msg)")
}

//3.
func test(msg: String) -> String {
print("重载的test()函数\(msg),带返回值")
return "test"
}

//4 这不算重载, 仅有形参名一样是不行的
func test(message:String){
print("重载的test()函数\(message)")
}

//调用1
test()

//调用2
var result:Void = test("Jike")

//调用3
var result2: String = test("Welcome , Geek")

嵌套函数

函数体内部所定义的函数

func getMathFunc(jackliu: String) -> (Int) ->Int{

func squre (num:Int) -> Int{
    return num * num
}

func cube (num:Int) ->Int{
    return num * num * num
}

switch(jackliu){
case "squre":
    return squre
default: 
    return cube
}
}

var mathFunc:(Int)->Int  = getMathFunc ("squre")
var mathFunc = getMathFunc ("squre") // 这样写说明即使不写变量的类型,系统也会进行推断
print(mathFunc(4)) //outcome is 16

mathFunc = getMathFunc ("other")
print(mathFunc(4)) //outcome is 64

Closure

一段可以作为参数传递给函数的代码

{ (parameters) -> return type in

 statements to execute

}

例子

var bids = [48.1, 75.4, 63.7, 52.4, 68.2]
var orderedBids = bids.sort( {(bid1: Double, bid2:Double) -> Bool in
    return  bid2 > bid1
})
print(orderedBids)

Closure的简写形式

Example - 原有形式

var soups = ["tomato", "hot and sour", "french onion", "vegetable"]
var alphabeticalSoups = soups.sort({(soup1: String, soup2: String) -> Bool in
    return soup2 > soup1
})

Example - 简写 ($0,$1,$2….分别代表第几个参数)

var soups = ["tomato", "hot and sour", "french onion", "vegetable"]
var hello = soups.sort({

    $1 > $0

})   

闭包的应用

func getMathFunc(jackliu: String) -> (Int) ->Int{

switch(jackliu){
case "squre":
    return { (num: Int) -> Int in
        return num * num
    }
default:
    return { (num:Int) -> Int in
        return num * num * num

    }
}
}

var mathFunc = getMathFunc("squre")
print(mathFunc(5)) //outcome is 25
mathFunc = getMathFunc ("other")
print(mathFunc(5)) //outcome is 125

利用上下文推断类型

Swift可以推断闭包的形参类型和返回值类型
函数和闭包是统一的,函数和闭包都是引用类型,当赋值给变量时,不会复制,而是指向同一个闭包

省略形参类型,因为从左侧就可以推断了

var squre:(Int) -> Int = {(num) in return num * num}
print(squre(3))   //outcome is 9

因为可以推断,所以小括号也是可以省略的

var squre:(Int) -> Int = {num in return num * num}
print(squre(3))   //outcome is 9

如果闭包表达式只有一行代码,而且这行代码就是返回值,也可以省略return。通过$0,$1…来引用第一个,第二个参数

var squre:(Int) -> Int = {$0 * $0}
print(squre(3))  //out come is 9

var result: Int = { //这里的Int不是返回值类型,而是形参
    var result = 1
for i in 1...$1{
   result *= $0
}
return result
}(4,3)
print(result) //outcome is 64

捕获上下文中的变量或者常量

闭包(嵌套函数)可以访问或者修改其所在上下文中的变量或常量

func makeArr(ele:String) -> () -> [String]{

//创建一个不包含任何元素的数组
var arr: [String] = []
func addElement() ->[String]{

//向arr数组中添加一个元素
arr.append(ele)

return arr
}
return addElement
}