函数
func about() -> Void {
print("iPhone 7s")
}
abount()
func callPhone(phoneNumber: String) {
print("打电话给:\(phoneNumber)")
}
callPhone(phoneNumber: "+86 110")
func readMessage() -> String {
return "吃饭了吗?"
}
let msg = readMessage()
print(msg)
func sum(num1: Int, num2: Int) -> Int {
return num1 + num2
}
let result = sum(num1: 20, num2: 30)
print(result)
let nums = [10, 11, 15, 20, 111]
func getOddEvenCount(nums: [Int]) -> (Int, Int) {
var oddCount = 0
var evenCount = 0
for n in nums {
if n % 2 = 0 {
evenCount += 1
} else {
oddCount += 1
}
}
return (oddCount, evenCount)
}
let tuple = getOddEvenCount(nums: nums)
print("奇数:\(tuple.0) 偶数:\(tuple.1)")
* 基础用法
1. 每个函数参数都有一个参数标签(argument label) 和 一个参数名称(parameter name);
2. 参数标签在调用函数的时候使用,调用的时候需要将函数的参数标签写在对应的参数名称前面;
3. 参数名称在函数的实现中使用;
4. 默认情况下,函数参数使用参数名称来作为它们的参数标签。
实例代码:
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)"
}
print(greet(person: "Bill", from: "Cupertino"))
** 忽略参数标签:使用一个下划线(_)来代替一个明确的参数标签
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
print(firstParameterName, secondParameterName)
}
someFunction(1, secondParameterName: 2)
*** 默认参数:在函数体中通过给参数赋值来为任意一个参数定义默认值
func makeCoffee(coffeeName: String = "雀巢") -> String {
return "制作了一杯爱心的\(coffeeName)咖啡。"
}
makeCoffee()
makeCoffee(coffeeName: "拿铁")
makeCoffee(coffeeName: "卡布奇诺")
**** 可变参数:一个函数最多只能拥有一个可变参数
func sum(nums: Int...) Int {
var total = 0
for n in nums {
total += n
}
return total
}
sum(nums: 20, 30, 40)
***** 输入输出参数
1. 函数参数默认是常量;
2. 想要一个函数可以修改参数的值,并且想要这些修改在函数调用结束后仍然存在;
3. 应该把这个参数定义为输入输出参数,并且只能传递变量给输入输出参数;
4. 用 inout 修饰的参数,不能设定默认值。
示例代码:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var anotherInt = 107
swap(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
1. 定义:由函数的参数类型和返回类型组成。
示例代码:
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
2. 作为数据类型
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 = addTwoInts
print("Result: \(mathFunction(2, 3))")
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
let anotherMathFunction = addTwoInts
3. 作为返回类型
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
print("Counting to zero")
while currentValue != 0 {
print("\(currentValue)")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
闭包
三种形式:
1. 全局函数:一个有名字但不会捕获任何值的闭包;
2. 嵌套函数:一个有名字并可以捕获其封闭函数域内值的闭包;
3. 闭包表达式:一个利用轻量级语法所写的可以捕获和存储其上下文中常量或者变量的匿名闭包。
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: backward)
print("reversedNames")
1. 类型:(形参列表) -> 返回值;
2. 值:{ (形参列表) -> 返回值 in 代码块 };
3. 调用:常量或变量名称(形参列表);
4. 不能在闭包参数中设置默认值。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print("1: \(reversedNames)")
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2})
print("2: \(reversedNames)")
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 })
print("3: \(reversedNames)")
reversedNames = names.sorted(by: { $0 > $1 })
print("4: \(reversedNames)")
reversedNames = names.sorted(by: >)
print("5: \(reversedNames)")
1. 闭包在其被定义的上下文中捕获常量或者变量;
2. 即使定义这些常量和变量的原作用域已经不存在;
3. 闭包仍然可以在闭包函数体内引用和修改这些值。
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
let incrementBySeven = makeIncrementor(forIncrement: 7)
incrementBySeven()
1. 将函数或者闭包赋值给一个常量还是变量;
2. 实际上都是将常量或者变量的值设置为对应函数或者闭包的引用。
1. 需要将一个很长的闭包表达式作为最后一个参数传递给函数;
2. 在使用尾随闭包时,可以将闭包表达式书写在函数括号之后;
3. 在使用尾随闭包时,不用写出它的参数标签。
示例代码:
func calculate(opr: String, funN: (Int, Int) -> Int) {
switch opr {
case "+":
print("10 + 5 = \(funN(10, 5))")
default:
print("10 - 5 = \(funN(10, 5))")
}
}
calculate(opr: "+", funN: { (a: Int, b: Int) -> Int in return a + b })
calculate(opr: "-") { (a: Int, b: Int) -> Int in return a + b }
如果闭包表达式是函数或者方法的唯一参数,则使用尾随闭包时,可以把 () 省略掉
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted { $0 > $1 }
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 { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
print(strings)
1. 一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行;
2. 在参数类型之前标注 @escaping;
3. 在逃逸闭包中,必须显示地引用 self。
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure {
self.x = 100
}
someFunctionWithNonescapinClosure {
x = 200
}
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)
1. 一种自动创建的闭包,用于包装传递给函数作为参数的表达式;
2. 不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值;
3. 在参数类型之前标注 @autoclosure;
4. 一般用来延迟求值。
示例代码:
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
let customerProvider = {customersInLine.remove(at: 0)}
print(customersInLine.count)
print("Now serving \(customerProvider())!")
print(customersInLine.count)
func serve(customer customerProvider: () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))