今天学习的内容是有关函数、闭包的知识.
1.函数
- 1.1 函数名、函数参数命名
苹果编写函数的风格,就是函数的命名更加类似于自然语句,有着非常强的可读性.正常我们的函数是是这样定义的:
func sayHelloTo(name: String, greeting: String) -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("jf", greeting: "hello")
参数:greeting 既是函数外部参数名,也是函数内部参数名
要是我们想要区分开,使得调用时,语义看起来更明确,又不会影响内部函数的参数调用,这时我们应该这样写:
func sayHelloTo(name: String, withGreeting greeting: String) -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("jf", withGreeting: "hello")
还有一种情况,函数名已经十分明确了,这时候我们不需要函数外部参数名,该如何定义呢,请看:
func mutiply(num1: Int, _ num2: Int) -> Int {
return num1 * num2
}
mutiply(1, 3)
- 1.2 默认参数值和可变参数值
有默认参数值
// 建议有默认参数值的参数放在最后面
func sayHelloTo(name: String, withGreeting greeting: String = "Hello") -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("dd")
sayHelloTo("jf", withGreeting: "hello")
变长的参数类型,对于一个函数最多有一个变长参数类型
func sayHelloTo(names: String ..., withGreeting greeting: String) {
for name in names {
print("\(name), \(greeting)")
}
}
sayHelloTo("jf", "DC", withGreeting: "Hello")
- 1.3 常量参数、变量参数、inout参数
一般,我们传入函数的参数是默认为常量参数,如果需要一个变量参数(事实上,由于面向函数的原则,不建议声明架构一个函数包含有变量参数。),则需要在函数体内标注:var num = num.
// 十进制数转二进制
func toBinary(num: Int) -> String {
var num = num
var res = ""
repeat {
res = String(num % 2) + res
num /= 2
} while num != 0
return res
}
toBinary(12)
inout参数:可以改变传入的值,做到按引用传入.
// 交换两个整数
func swapTwoInts(inout a: Int, inout _ b: Int) {
let t: Int = a
a = b
b = t
}
var x = 1
var y = 2
swapTwoInts(&x, &y) // 传入参数前加上&
x // 2
y // 1
- 1.4 函数型类型
函数本身是可以被当做变量的
// 函数本身是可以被当做变量的
var array1 = ["F", "P", "C", "D", "A", "S"]
func stringSortDesc(a: String, _ b: String) -> Bool {
return a > b
}
let array2 = array1.sort(stringSortDesc)
array2
func sayHelloTo(names: String ..., withGreeting greeting: String) {
for name in names {
print("\(name), \(greeting)")
}
}
func toBinary(num: Int) -> String {
var num = num
var res = ""
repeat {
res = String(num % 2) + res
num /= 2
} while num != 0
return res
}
// 函数变量
let tobinary: (Int)->String = toBinary
let sayhello: (String ...,String)->() = sayHelloTo
下面了解初步的函数式编程例子
var score = [99, 20, 60, 80, 30, 21]
// map
func isPassOrFail(score: Int) -> String {
return score < 60 ? "Fail" :"Pass"
}
score.map(isPassOrFail)
// filter
func arrayLower60(score: Int) -> Bool {
return score < 60
}
score.filter(arrayLower60)
// reduce
func concatenate(str: String, score: Int) -> String {
return str + "\(score)" + " "
}
score.reduce("", combine: concatenate)
// 从大到小-转成字符串
score.sortInPlace { (score1, score2) -> Bool in
return score1 > score2
}
score.reduce("", combine: concatenate)
- 1.5 返回值为函数类型,函数嵌套
例如:
对于买家购买的商品,所付的钱 = 邮费 + 单价 * 体重/钱
而邮费的计算是根据体重,有不同的标准
标准1:小于20,邮费 = 体重
标准2:大于20,邮费 = 体重 * 2
func postage1(weight: Int) -> Int {
return weight
}
func postage2(weight: Int) -> Int {
return weight * 2
}
func choosePostage(weight: Int) -> (Int) -> Int {
return weight < 20 ?postage1 :postage2
}
func calculateGoodPrice(weight: Int, price: Int) -> Int {
let postage = choosePostage(weight)
return postage(weight) + weight * price
}
calculateGoodPrice(30, price: 10)
函数嵌套
func postage1(weight: Int) -> Int {
return weight
}
func postage2(weight: Int) -> Int {
return weight * 2
}
func calculateGoodPrice(weight: Int, price: Int) -> Int {
func choosePostage(weight: Int) -> (Int) -> Int {
return weight < 20 ?postage1 :postage2
}
let postage = choosePostage(weight)
return postage(weight) + weight * price
}
calculateGoodPrice(30, price: 10)
2.闭包
闭包和函数本质上是一致的,都属于引用类型.
学过OC的朋友,就可以把闭包当做block来理解.
闭包的基本语法
let hello = {(name: String, greeting: String) -> String in
// 函数体
return "\(name): \(greeting)"
}
一对大括号,参数列表,返回类型,关键字in
,加上函数体
结尾闭包:若函数最后一个参数是闭包,则闭包可以写在小括号()后面,例如
let showView = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
showView.addSubview(rectangle)
rectangle.center = showView.center
rectangle.backgroundColor = UIColor.redColor()
UIView.animateWithDuration(2.0) {
rectangle.backgroundColor = UIColor.blueColor()
rectangle.frame = showView.frame
}
内容捕获:在闭包内,可以获取到闭包外的变量(但是得注意内存问题,还有待研究)
为大家介绍用typealias,为闭包重新定义名字
typealias SayHello = (name: String, greeting: String) -> Void
let sayHello: SayHello? = {name, greeting in
print("\(name): \(greeting)")
}
sayHello!(name: "jj", greeting: "Hi")
let hello = {(name: String, greeting: String) -> String in
// 函数体
return "\(name): \(greeting)"
}
swift中没有main函数
@UIApplicationMain:表示程序入口
大家赶紧去试试吧!
刘雨波Demo地址:
Play-with-Swift-2