这一节将会涉嫌斯威夫特中其余的有关函数的接纳,这一个剧情包括有:
那壹节将会提到斯维夫特中此外的关于函数的施用,那一个内容包罗有:
函数
后天求学的始末是关于函数、闭包的知识.
1.函数
暗中同意参数值和可变参数值、常量参数、再次回到函数类型和函数嵌套:
暗中同意参数值和可变参数值、常量参数、重临函数类型和函数嵌套:
函数基础
在Swift中,函数前边要用func关键字评释,参数写在括号里,并用向右的箭头指向重临值的门类。
func sayHello(name: String?) -> String {
return "Hello " + (name ?? "Guest")
}
var nickName : String? = nil
sayHello(nickName)
nickName = "MC"
sayHello(nickName)
//无参数,无返回值
func printHello1() {
print ("Hello")
}
func printHello2() -> (){
print ("Hello")
}
func printHello3() -> Void{
print ("Hello")
}
- 一.一 函数名、函数参数命名
苹果编写函数的品格,就是函数的命名越发接近于自然语句,有着不行强的可读性.平日大家的函数是是这么定义的:
壹、暗中同意参数值和可变参数值
一、暗许参数值和可变参数值
采纳元组重回四个值
无时无刻要思考到函数的参数或重临类型为可选型的处境。
func findMaxAndMin (numbers:[Int]) -> (max:Int , min:Int)? {
guard numbers.count > 0 else {
return nil
}
var minValue = numbers[0]
var maxValue = numbers[0]
for number in numbers {
minValue = minValue < number ? minValue : number
maxValue = maxValue > number ? maxValue : number
}
//return返回的元组里面的各个分量可以不用指明变量名,如果指明必须与函数返回值声明的时候一样。
return (maxValue , minValue)
}
var scores: [Int]? = [202,123,4324,543,123]
scores = scores ?? []
if let result = findMaxAndMin(scores!) {
print("The max score is \(result.max)")
print("The min score is \(result.min)")
}
对私下认可参数值是指在函数的扬言中就曾经定义了参数的初值,比如:
对私下认可参数值是指在函数的扬言中就早已定义了参数的初值,比如:
其间参数名与外部参数名
Swift的函数暗中认可会不出示第3个参数的参数名,但背后的参数会来得出他们的参数名,但那不是相对的,后边会提到当中参数名和外部参数名的定义。
func sayHelloTo(name: String , greeting: String) -> String {
return "\(greeting),\(name)!"
}
//sayHelloTo("Playground", "Hello") //会报错
sayHelloTo("Playground", greeting: "Hello")
Swift中等高校函授数的每八个参数都足以有1个之中参数名和贰个外部参数名。外部函数名用于调用函数时展现。未有外部参数名时,原来的参数名默感觉内外参数名,当然大家也足以用下划线”_”来让函数被调用时不展现参数名。
func sayHelloTo(name: String , withGreetingWord greeting: String) -> String {
return "\(greeting),\(name)!"
}
sayHelloTo("Playground", withGreetingWord: "Hello")
func mutiply (num1 : Int , _ num2 : Int) -> Int {
return num1 * num2
}
mutiply(2, 3)
前后参数名的选拔景况:往往是上边调用者来调用函数,使语义尤其旗帜明显,苹果官方就是这么做的:
var arr = [1,2,3,4,5]
arr.insert(5, atIndex: 3)
max(2, 3)
补充:下划线”_”近日大家在for-in循环,switch语句和元组中都用到过,那里在函数参数名的时候也运用了。
func sayHelloTo(name: String, greeting: String) -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("jf", greeting: "hello")
func sayHelloTo(name:String,greeting:String = “Hi”, punctuation:String = “!”){
}
在调用的时候可以是:
sayHelloTo(name:“PlayGround”, punctuation :“!!!”, greeting :“Hi”)
func sayHelloTo(name:String,greeting:String = “Hi”, punctuation:String = “!”){
}
在调用的时候可以是:
sayHelloTo(name:“PlayGround”, punctuation :“!!!”, greeting :“Hi”)
暗许参数值与可变参数
当2个函数有私下认可参数值时,调用函数的时候会多一种调用方式,即不显示暗中认可参数名称,相应的参数值为暗中认可值。暗许参数之间的依次是能够改变的。暗中同意参数能够放在参数列表的末梢,也能够不放在最后,但此时要留意,当私下认可参数不在参数列表最终的时候,参数之间的调用顺序是无法改变的。
func sayHelloTo (name: String , withGreetingWord greeting: String = "Hello" , punctuation: String = "!") -> String{
return "\(greeting), \(name)\(punctuation)"
}
sayHelloTo("MC")
sayHelloTo("MC", withGreetingWord: "Hi")
sayHelloTo("MC", withGreetingWord: "Hi", punctuation: "!!!")
sayHelloTo("MC", punctuation: "!!!")
sayHelloTo("MC", punctuation: "!!!" , withGreetingWord: "Hi")
对此二个函数来讲,最多只好有贰个变长参数类型
func mean( numbers: Double ...) -> Double {
var sum: Double = 0
//将变长参数当做一个数组看待
for number in numbers {
sum += number
}
return sum / Double(numbers.count)
}
mean(2)
mean (2,3,4,5)
参数:greeting 既是函数外部参数名,也是函数内部参数名
借使大家想要区分开,使得调用时,语义看起来越来越强烈,又不会影响内部函数的参数调用,那时我们应当这么写:
因为对有默许参数的函数来说,有暗许参数值的参数是能够轮换顺序的,不过不建议如此使用。print函数就是有分割符和了结符初步值的函数。
因为对有暗中认可参数的函数来讲,有默许参数值的参数是足以替换顺序的,不过不提议如此使用。print函数便是有分割符和了结符初阶值的函数。
常量参数,变量参数与inout参数
在Swift二.第22中学,函数参数注明为var将会发出3个告诫。在斯维夫特3.0中,该语法将被撤除。约等于说,对于函数的参数,大家将依然钦点为inout类型,只怕不点名,默以为let参数。假若急需二个变量参数,则须要在函数体内标注: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
}
var x = 100
toBinary(x) //1100100
x //x的值并没有被改变
Swift之函数与闭包,斯维夫特基础学习的下结论。若要在函数内修改完二个值之后,在函数外这一个值依然是被转移的,则要在函数参数类型上注明inout类型,并且在传参数的时候,参数前面要加2个取址符号”&”。
func swapTwoInts(inout a:Int , inout _ b:Int) {
(a , b) = (b , a)
}
var x:Int = 1
var y:Int = 2
swapTwoInts(&x, &y)
x //2
y //1
瞩目:斯威夫特里的数组,字典,集合等都是按值传递的。
func initArray(inout arr:[Int] , by value:Int) {
for i in 0..<arr.count {
arr[i] = value
}
}
var arr = [1,2,3,4,5]
initArray(&arr, by: 0)
arr //[0,0,0,0,0]
func sayHelloTo(name: String, withGreeting greeting: String) -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("jf", withGreeting: "hello")
对变长的参数类型的函数来说,
对变长的参数类型的函数来讲,
运用函数类型
在Swift中等高校函授数也足以视作一个变量,也有相应的类别,即函数型变量。
func add(a:Int , _ b:Int) -> Int {
return a + b
}
let anotherAdd = add //(Int, Int) -> Int类型
anotherAdd(3,4)
//无参数无返回值类型的函数类型可以有下面四种方式表示:
() -> ()
() -> Void
Void -> ()
Void -> Void
下边举3个在实质上编制程序中会用到函数类型的例子:
var arr:[Int] = []
for _ in 0..<100 {
arr.append(random()%1000)
}
arr.sort() //默认从小到大排序
arr.sort(<#T##isOrderedBefore: (Int, Int) -> Bool##(Int, Int) -> Bool#>)
//里面可以传一个(Int, Int) -> Bool类型的函数来告诉数组怎么排序.
//从大到小
func biggerNumberFirst(a:Int , _ b:Int) -> Bool {
return a > b
}
arr.sort(biggerNumberFirst)
//按照字符串的字典序进行排序
func cmpByNumberString(a:Int , _ b:Int) -> Bool {
return String(a) < String(b)
}
arr.sort(cmpByNumberString)
//按照距离500最近的数排序
func near500(a:Int , _ b:Int) -> Bool {
return abs(a - 500) < abs(b - 500)
}
arr.sort(near500)
还有1种情形,函数名曾经十一分鲜明了,那时候我们不须求函数外部参数名,该怎么着定义呢,请看:
func mean(numbers : Double ...)-> Double {
for number in numbers {
sum+=number
}
return sum/Double(numbers.count)
}
调用可以是:
mean(2)
也可以是
mean(2,3,4,5,6)
func mean(numbers : Double ...)-> Double {
for number in numbers {
sum+=number
}
return sum/Double(numbers.count)
}
调用可以是:
mean(2)
也可以是
mean(2,3,4,5,6)
函数式编制程序起头
大家以改分系统为例来介绍这一个章节的始末:
//常用写法
func changeScores1(inout scores:[Int]){
for (index , score) in scores.enumerate() {
scores[index] = Int(sqrt(Double(score)) * 10)
}
}
func changeScores2(inout scores:[Int]){
for (index , score) in scores.enumerate() {
scores[index] = Int(Double(score) / 150.0 * 100.0)
}
}
var scores1 = [36,61,78,89,99]
changeScores1(&scores1)
var scores2 = [88,101,124,137,150]
changeScores2(&scores2)
//改进写法
func changeScores(inout scores:[Int] , by changeScore: (Int) -> Int){
for (index , score) in scores.enumerate() {
scores[index] = changeScore(score)
}
}
func changeScores1(score:Int) -> Int{
return Int(sqrt(Double(score)) * 10)
}
func changeScores2(score:Int) -> Int{
return Int(Double(score) / 150.0 * 100.0)
}
数组内容的扩充:
//map
changeScores(&scores1, by: changeScores1)
scores1.map(changeScores1)
//返回值可以不仅仅是整型
func isPassOrFail(score: Int) -> String {
return score < 60 ? "Fail" : "Pass"
}
scores1.map(isPassOrFail)
//filter
func fail(score: Int) -> Bool {
return score < 60
}
scores1.filter(fail)
//reduce
var arr = [1,2,3,4,5]
func add(num1:Int , _ num2: Int) -> Int {
return num1 + num2
}
arr.reduce(0, combine: add)
arr.reduce(0, combine: +)
func concatenate(str:String , num: Int) -> String {
return str + String(num) + " "
}
arr.reduce("", combine: concatenate)
func mutiply(num1: Int, _ num2: Int) -> Int {
return num1 * num2
}
mutiply(1, 3)
唯独1个函数只好够有1个变长的参数。
然而三个函数只可以够有多个变长的参数。
归来函数类型与函数嵌套
函数能够当作再次回到值,并且函数内部能够嵌套函数:
//邮费选择
func tier1MailFeeByWeight(weight: Int) -> Int {
return 1 * weight
}
func tier2MailFeeByWeight(weight: Int) -> Int {
return 3 * weight
}
//总价钱
func feeByUnitPrice(price: Int , weight: Int) -> Int {
func chooseMailFeeCalculationByWeightt(weight: Int) -> (Int) -> Int {
return weight <= 10 ? tier1MailFeeByWeight : tier2MailFeeByWeight
}
let mailFeeByWeight = chooseMailFeeCalculationByWeightt(weight)
return mailFeeByWeight(weight) + price * weight
}
- 一.二 私下认可参数值和可变参数值
有默许参数值
闭包
贰、常量参数
2、常量参数
闭包的基础语法
斯维夫特里面包车型客车闭包,跟大家OC里面包车型大巴block基本是同1的。闭包本质上正是函数。
var arr:[Int] = []
for _ in 0..<100{
arr.append(random()%1000)
}
func biggerNumberFirst(a:Int , _ b:Int) -> Bool {
return a > b
}
arr.sort(biggerNumberFirst)
//使用闭包
arr.sort({ (a:Int,b:Int) -> Bool in
return a > b
})
// 建议有默认参数值的参数放在最后面
func sayHelloTo(name: String, withGreeting greeting: String = "Hello") -> String {
return "say \(greeting) to \(name)"
}
sayHelloTo("dd")
sayHelloTo("jf", withGreeting: "hello")
与Java和C/C++分化,Swift无法在函数中退换参数的值,因为传播参数的值的花色证明是let,好的函数会尽量防止必要转移函数参数的值。
与Java和C/C++差异,Swift不得以在函数中改动参数的值,因为传播参数的值的项目评释是let,好的函数会尽量制止供给改动函数参数的值。
闭包语法的简化
对此一句话的闭包,大家能够有如下的化简:
arr.sort({ (a:Int,b:Int) -> Bool in
return a > b
})
arr.sort({ (a:Int,b:Int) -> Bool in return a > b})
arr.sort({ a , b in return a > b})
arr.sort({ a , b in a > b})
arr.sort({ $0 > $1})
arr.sort(>)
变长的参数类型,对于贰个函数最多有三个变长参数类型
而是只要要改成参数的值,须求如此来声称:
可是1旦要改成参数的值,需求如此来声称:
谈到底闭包
当闭包为二个函数要传播的终极二个参数时,闭包能够写在括号的外场。
arr.sort({ a , b in return a > b})
arr.sort(){ a, b in
return a > b
}
arr.sort{ a, b in
return a > b
}
func sayHelloTo(names: String ..., withGreeting greeting: String) {
for name in names {
print("\(name), \(greeting)")
}
}
sayHelloTo("jf", "DC", withGreeting: "Hello")
func toBinary(var num:Int)-> String {
return num/2
}
func toBinary(var num:Int)-> String {
return num/2
}
剧情捕获
日前大家所用的闭包,都是用来作为函数来利用的,但在一些场馆下,闭包是有投机特别的优势的。
//sort里面传入的函数类型是确定的,我们无法传递第三个参数,这时可以利用闭包的内容捕获功能来解决这个问题。
arr.sort(<#T##isOrderedBefore: (Int, Int) -> Bool##(Int, Int) -> Bool#>)
var arr:[Int] = []
for _ in 0..<100{
arr.append(random()%1000)
}
arr.sort{ a, b in
abs(a - 500) < abs(b - 500)
}
var num = 300
arr.sort{ a, b in
abs(a - num) < abs(b - num)
}
- 一.三 常量参数、变量参数、inout参数
相似,大家传入函数的参数是暗中同意为常量参数,假使急需多个变量参数(事实上,由于面向函数的规则,不建议表明架构3个函数包罗有变量参数。),则要求在函数体内标注:var
num = num.
将品种申明为var,
将品种注解为var,
闭包和函数是援引类型
从前大家说过,斯威夫特中数组,字典和汇聚都以值类型,今后我们将触发到斯威夫特中的第2个引用类型。
func runningMetersWithMetersPerDay(metersPerDay: Int) -> () -> Int {
var totalMeters = 0
return {
totalMeters += metersPerDay
return totalMeters
}
}
var planA = runningMetersWithMetersPerDay(2000)
planA() //2000
planA() //4000
planA() //6000
var planB = runningMetersWithMetersPerDay(5000)
planB() //5000
planB() //10000
planB() //15000
var anotherPlan = planB
anotherPlan() //20000
//证明是引用类型
planB() //25000
唯独那样的改观只是在函数的内部改变,可是在函数的外围是不退换的,
澳门葡京备用网址 ,可是如此的变动只是在函数的内部退换,可是在函数的外界是不更改的,
// 十进制数转二进制
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)
那是因为那种方式是按值出流传的,不是引用传入,只是在函数的中间开始展览了copy
那是因为这种格局是按值出流传的,不是引用传入,只是在函数的中间开始展览了copy
inout参数:能够变动传入的值,做到按引用传入.
假若要求痛殴函数更换外部参数的值,需求增加inout
一旦急需痛殴函数退换外部参数的值,要求增加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
func swapInt(inout a :Int, inout b : Int){
(a,b) = (b,a)
}
var x : Int = 1
var y : Int = 2
swapInt(&x,&b)
func swapInt(inout a :Int, inout b : Int){
(a,b) = (b,a)
}
var x : Int = 1
var y : Int = 2
swapInt(&x,&b)
- 一.四 函数型类型
函数本人是足以被当作变量的
3、重回函数类型
3、重返函数类型
// 函数本身是可以被当做变量的
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
本条也很不难,重返的体系是函数就好了:
以此也很简单,重临的门类是函数就好了:
上面通晓开始的函数式编制程序例子
func tire1 (weight : Int)-> Int {
}
func tire2 (weight : Int ) ->Int {
}
func choose (weight : Int) -> (Int) -> Int {
return weight>10 ? tire1(weight) : tire2(weight)
}
func tire1 (weight : Int)-> Int {
}
func tire2 (weight : Int ) ->Int {
}
func choose (weight : Int) -> (Int) -> Int {
return weight>10 ? tire1(weight) : tire2(weight)
}
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)
- 一.伍 重临值为函数类型,函数嵌套
例如:
4、函数的嵌套
4、函数的嵌套
func feeByPrice(price : Int,weight:Int)->Int {
func choose (weight : Int) -> (Int) -> Int {
return weight>10 ? tire1(weight) : tire2(weight)
}
return ...
}
func feeByPrice(price : Int,weight:Int)->Int {
func choose (weight : Int) -> (Int) -> Int {
return weight>10 ? tire1(weight) : tire2(weight)
}
return ...
}
对于买家购买的商品,所付的钱 = 邮费 + 单价 * 体重/钱
而邮费的计算是根据体重,有不同的标准
标准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)"
}
1对大括号,参数列表,重临类型,关键字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