swift 函数.和匿名函数

函数

注意: 没有定义返回类型的函数会返回特殊的值,叫 Void。它实际上是一个空的元组(tuple),没有任何元素,能够写成()。
使用元组做为返回参数,返回多个参数git

  func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {
    var vowels = 0, consonants = 0, others = 0
    for character in string {
        switch String(character).lowercaseString {
        case "a", "e", "i", "o", "u":
            ++vowels
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
          "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
            ++consonants
        default:
            ++others
        }
    }
    return (vowels, consonants, others)
}

外部参数名

外部参数名..是为了调用该函数时让其参数更为有表现力,更为通顺,同时还保持了函数体是可读的和有明确意图的。让别人阅读整段代码时更方便
当其余人在第一次读你的代码,函数参数的意图显得不明显时,考虑使用外部参数名。若是函数参数名的意图是很明显的,那就不须要定义外部参数名了数组

  func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String {
      return s1 + joiner + s2
  }

  join(string: "hello", toString: "world", withJoiner: ", ")

若是你须要提供外部参数名,可是局部参数名已经定义好了,那么你不须要写两次参数名。相反,只写一次参数名,并用井号(#)做为前缀就能够了。这告诉 Swift 使用这个参数名做为局部和外部参数名。闭包

  func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
    for character in string {
        if character == characterToFind {
            return true
        }
    }
    return false
}

默认值

将带有默认值的参数放在函数参数列表的最后。这样能够保证在函数调用时,非默认参数的顺序是一致的,同时使得相同的函数在不一样状况下调用时显得更为清晰。
当你未给带默认值的参数提供外部参数名时,Swift 会自动提供外部名字。此时外部参数名与局部名字是同样的,就像你已经在局部参数名前写了井号(#)同样。函数

  func join(s1: String, s2: String, joiner: String = " ") -> String {
    return s1 + joiner + s2
}

  join("hello", "world", joiner: "-")
// returns "hello-world"

可变参数

一个可变参数(variadic parameter)能够接受一个或多个值.传入可变参数的值在函数体内当作这个类型的一个数组生命周期

  • 一个函数至多能有一个可变参数,并且它必须是参数表中最后的一个。这样作是为了不函数调用时出现歧义。
  • 若是函数有一个或多个带默认值的参数,并且还有一个可变参数,那么把可变参数放在参数表的最后。
func arithmeticMean(numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}

常量参数和变量参数

函数参数默认是常量。试图在函数体中更改参数值将会致使编译错误。这意味着你不能错误地更改参数值
注意: 对变量参数所进行的修改在函数调用结束后便消失了,而且对于函数体外是不可见的。变量参数仅仅存在于函数调用的生命周期中。内存

func alignRight(var string: String, count: Int, pad: Character) -> String {
    let amountToPad = count - countElements(string)
    for _ in 1...amountToPad {
        string = pad + string
    }
    return string
}

//下面这样会报错
func test(a:String){
  a = "sssss";
}

In-Out参数

  • 定义一个输入输出参数时,在参数定义前加 inout 关键字
  • 输入输出参数不能有默认值,并且可变参数不能用 inout 标记。若是你用 inout 标记一个参数,这个参数不能被 var 或者 let 标记。
  • 当传入的参数做为输入输出参数时,须要在参数前加&符,表示这个值能够被函数修改
  func swapTwoInts(inout a: Int, inout b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt);// "someInt is now 107, and anotherInt is now 3”

函数类型

函数类型,可让一个变量能够成为多个函数,同时能够把函数当参数进行传递或者当作返回值rem

var mathFunction: (Int, Int) -> Int = addTwoInts

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

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backwards ? stepBackward : stepForward
}

闭包

闭包能够捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。Swift 会为您管理在捕获过程当中涉及到的全部内存操做。
闭包采起以下三种形式之一:
全局函数是一个有名字但不会捕获任何值的闭包
嵌套函数是一个有名字并能够捕获其封闭函数域内值的闭包
闭包表达式是一个利用轻量级语法所写的能够捕获其上下文中变量或常量值的匿名闭包

闭包表达式:input

  { (parameters) -> returnType in
      statements
  }

闭包特性一:利用上下文推断参数和返回值类型

闭包做为函数参数的话,因为类型推断...能够省去闭包参数的类型和返回值闭string

  reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )
  reversed = sorted(names, { s1, s2 in return s1 > s2 } )

闭包特性二:隐式返回单表达式闭包,即单表达式闭包能够省略return关键字

包函数体内若是是单一表达式,还能够省去return语句it

  reversed = sorted(names, { s1, s2 in s1 > s2 } )

闭包特性三:参数名称缩写

  • 1 当使用参数名称缩写的时候能够省去in
  • 2 运算符函数(Operator Functions)起做用还能够简写
reversed = sorted(names, { $0 > $1 } )
reversed = sorted(names, >)

闭包特性四:尾随(Trailing)闭包语法

若是您须要将一个很长的闭包表达式做为最后一个参数传递给函数,能够使用尾随闭包来加强函数的可读性。 尾随闭包是一个书写在函数括号以后的闭包表达式,函数支持将其做为最后一个参数调用。

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map {
    (var number) -> String in
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }
    return output
}

捕获值

闭包能够在其定义的上下文中捕获常量或变量。
即便定义这些常量和变量的原域已经不存在,闭包仍然能够在闭包函数体内引用和修改这些值。

闭包是引用类型。可是注意,当一个嵌套函数内的函数做为返回值的时候其实是建立了一个新的函数.

//全局函数
var str = "Hello, playground"
func test(a:String=""){
    println(str)
}
test();            //"Hello, playground"
str = "Hello";
test();            //"Hello"

//嵌套函数
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount   //runningTotal
        return runningTotal
    }
    return incrementor
}

let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
// 返回的值为10
incrementByTen()
// 返回的值为20
incrementByTen()
// 返回的值为30

//因为是建立了一个新函数..因此会像下面显示
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
// 返回的值为7
incrementByTen()
// 返回的值为40

//因为是引用类型.因此
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// 返回的值为50

注意: Swift 会决定捕获引用仍是拷贝值。 您不须要标注amount或者runningTotal来声明在嵌入的incrementor函数中的使用方式。 Swift 同时也处理runingTotal变量的内存管理操做,若是再也不被incrementor函数使用,则会被清除。

相关文章
相关标签/搜索