4 .Swift函数|闭包
在编程中,我们常把能完成某一特定功能的一组代码,并且带有名字标记类型叫做函数,在C语言中,我们知道函数名就是一个指针,它指向了函数体内代码区的第一行代码的地址,在swift中也具有同样的功效。
在Swift中函数的表现形式如下:
1. func 函数名(参数名1:参数类型,参数名2,参数类型)->返回值类型 {函数的实现部分}
func sayHello()->Void {
print("hello world")
}
//有参数,有返回值,
func sayHello2(personName:String)->String {
let msg:String = "hello" + personName + "!"
return msg
}
sayHello2("a gan zuo")
// 有参数 无返回值
func showPersonInfo(personName:String,personAge:Int) ->Void {
print("\(personName)今年\(personAge)岁")
}
showPersonInfo("ZhangShan", personAge: 20)
//统计一段字符中制定字符的个数
let String = " I like you,I miss you,I love you,I hate you ,I wed you"
func count(str:String) -> (me:Int,you :Int other:Int) {
var m = 0,y = 0, o = 0
for char in str.characters {
switch char {
case "I":
m++
case "u":
y++
default:
o++
}
}
return (m,y,o)
}
let showCharacterCount = count(String)
showCharacterCount.0
showCharacterCount.me
2. 函数参数的内部名和外部名之分, 其本质作用就是为了再调用函数时候能看到这个参数标示的是什么值,例如 是年龄的值,还是是名字的值
func fa1(innerName: Int) { innerName为函数的内部名,第一个参数如果前面只有一个标示类似于这样就叫做内部名 }
函数的外部名,只能在函数外部使用,函数的内部名只能在函数的内部使用,在内部名前面加上一个空格和一个字符串标识就成了外部名
func fa(exteraName innerName:LocalName:Int) {
print("inner name:\(innerName)") //此处如果换成外部名 exteraName 则程序会报错
}
fa(externaName:123) // 外部名externaName只在外部做属性内容标示时使用
函数的从 第二个参数开始 及以后的参数默认即是内部名,又是外部名
func show(name:String, age:Int) {
//第一个name为内部名, 第二个age为内部或者外部名
print("\(name)的年龄是\(age)")
}
show("zhangshan", age: 31)
/**如果不希望使用默认的外部名,可以自己起外部名,在内部名的前面起一个名字空格隔开就是外部名*/
func pointWithX(x:Int ,AndY y:Int) {
print("point(\(x),\(y))")
}
pointWithX(3, AndY: 2) //此处在默认的第二个参数前加上了 AndY空格标示更改了原来的外部名 y,而第一个参数默认是内部名,所以前面没有标示。
/**如果不希望显示外部名,则在外部名前面挤上 万能数字 _ 下划线 */
func point(x:Int, _ y:Int) { }
point(100,200)
3. 函数的默认值,一个函数的参数可以设一个默认值,如果这个参数没有传入值,则使用默认值,如果传入了就使用新的值。
func printArray(array:[Int] ,separate:String = ",",flag:Bool) {
if flag { print "["}
for var i = 0;i <array.count - 1;i++ { print("\(array[i]\(separate))")}
if flag{print("]")}
}
var array = [9,5,2,7]
printArray(array,flag:ture) //使用默认值
printArray(array,separate:"_",flag:ture) //不使用默认值
/**函数的可变长参数,使用 类型名+ ... 表示有一堆这种类型的参数*/
fun getAvg(numbers:Double...) ->Double {
var total = 0.0
for num in numbers {
total += num
} return total/Double(numbers.count)
}
getAvg(2.0,3.0,8.0)
/**C语言中的可变长参数
#include <stido.h>
#include <stdarg.h>
float sum(int n,...) { //n代表元素的个数,....代表可变参数
va_list p; //定义了一个指针p
va_start(p,n) //定义了指针开始的元素位置
for (int i = 0; i<n; i++) {
sum += va_arg(p,double) //va_arg每调用一次p指针后移动一个元素
}
}
*/
4. 函数的重载的条件,
a.有两个及两个以上的方法,且方法名相同,参数个数,参数类型,参数顺序不同均满足
b.参数列表不同,参数外名不通,都可以形成重载关系
//有参与无参数
func test1(){}
func test1(a:Int){}
func test2(a:Int) {}
func test2(a:Int,b: Int) {}
func sayHello(a:String,b:Int) {}
fun sayHello(b:String,a :Int) {}
fun test3(a:Int,b :String) {}
fun test3(a:Int,B b:String) {}
5. 函数的类型*******重点,当一个函数声明部分,去掉了函数名字,那么剩下的部分就函数了
var x:Int //Int 类型变量
void test(){} void() //C函数类型 void(*pfun)() //C函数指针类型
Int getMax(int x,int y) //int (int x,int y)类型,int(*pfun)(int x,int y) //函数的指针类型
func sayHello() { print("hello")}
// ()->(Void):Swift中无参无返回值的类型,void可以省略,代表没有参数,与C语言中Void相似。
下面定义了一个(Int,Int)->Int 型的函数,能指向这一类型的函数,我们可以通过构造这种类型函数的不通逻辑,来实现加 减 乘 除
func addTwoInts(a: Int,b :Int)->Int { return a + b}
func addTwoInts(a: Int,b: Int)->Int { return a - b}
//函数也可以作为一种变量来进行赋值,将一个函数赋值给另外一个变量,根据前面学到过的Swift自动推算类型,左边被赋值的变量也变成了和它具有一样功能的函数了
var function = subTwoInts //函数指针赋值。
var function1:(Int,Int) ->Int = addTwoInts //同前面所学的类型标注,函数名也可以拿来作为类型标注。
function2(100,200) //无类型标注,我们看不到第二个参数的 外部参数名
function(100, b:200) //赋值时有使用函数类型标注,我们可以看到第二个参数的外部名
//定义一个函数,赋值sayHello要求带一个类型标注,带一个参数
func sayHello(content:String) { print("\(content)")}
var function3:(String) ->() = sayHello
function3("hello baby!")
/** 定义一个函数,赋值sayHello要求类型标注,不带参*/
func sayHello2() {
print("no arguments,no return values")
}
var function4:()->() = sayHello2
function4()
//下面主要进行无参无返回值的变换,根据标注类型的不同进行变换
var function5:()->(Void) = sayHello2
var fucntion6:(Void)->(Void) = sayHello2
var function7:Void ->Void = sayHello2
var function8 = sayHello2 //此步骤需要先知道sayHello2的函数类型,自动推导获得,相比OC最大的进步也就是自动推导了
function8()
//写一个整形参数,返回两个数的乘积
func mulTwoInts(a :Int,b :Int) ->Int { return a * b } //当代码中只有一行语句时,可以省略return关键字
// 写一个函数,传入一个函数类型参数。
func getResult(function:(Int,Int)->Int)->Int { //在C中常是这样定义的int (*p)()(int,int)
let result = function(a,b)
return result
}
/**下面通过给getResult函数传入一个(Int,Int)->Int类型的函数 作为参数,内不调用该传入的函数,然后再传入 定义好的a,b变量*/
var a=100,b =99
func getResult(function:(Int,Int) ->Int) ->Int { let result = function(a,b) return result}
getresult(addTwoInts)
getresult(sunTwoInts)
getresult(mulTwoINts)
getresult { (a,b) ->Int in return a* b}
/** 函数数组 数组中的每个元素都是函数,c语言中对应的叫函数数组*/
var nums:[Int] = [1,2,3,4,5,6] ; nums[0]
var funs:[(Int,Int)->Int] = [addTwoInts,subTwoInts,mulTwoInts]
funs[0](100,200)
funs[1](100,200)
funs[2](100,200)
// 函数座位一个函数的返回值类型,此处定义了一个函数做为返回值。这个和OC中的Block做返回值还是有几分像
func test()->(Int,Int)->Int {
return addTowInts //只需要返回类型的函数 返回就可以了,这里对应的返回值函数类型 (Int,Int)->Int
}
/** 嵌套函数,如果传真则是返回加法函数,如果为假则返回其它函数*/
func twoInts(isAddBool)-> (Int,Int)->Int {
//此处我们除了可以使用已经定义好的 addTwoInts 和subTwoInts函数,还可以在此函数内部定义辅助函数,也可以作为私有函数,它的作用阈就限定在这个 {} 内
func addTwoInt2 (a :Int, b:Int)->Int ){ return a + b }
func subTwoInt2 (a: Int, b:Int)-> Int){ return a - b }
if isAdd { return addTwoInt2} else { return subTwoInts}
}
twoInts(ture)(100,200) //注意此处,实际是先调用TwoInts(ture) 此时返回一个 addTwoInt2函数
然后次函数传入(100,200)这两个参数相当于再调用addTwoInt2(100,200) 可得结果为300
6. 函数的闭包,Swift中重点之重点.
下面我们首先来了解一下它在其它语言中的表现形式:
Swift ---- Closure 闭包
Ruby OC -----Block 代码块
C++ -----Lambda 演算
javascript ------anonymous function 匿名函数
它的本质就是将一段代码封装起来,变成一个类似于变量的玩意;在Swift中如果一个 函数的参数 是 函数类型,那么可以将一个功能相同的代码(闭包)传给它。OC中的Block不能传函数类型,但可以传代码 。所以说闭包可以理解为函数,但是比函数的功能要多的多。
基本语法格式:
{ (参数列表)->返回值类型 in 执行代码语句}
而OC中Bloc的主要表现形式
^ 返回值类型(参数列表) {执行代码语句 }
//定义一个函数类型,或者是闭包类型,如下所示,只要函数类型与 闭包中 参数表->返回值类型 相同就可以警醒函数赋值。而 函数的实现体部分代码 即为 闭包内 in后面的代码
var sayClosure:(Int,Int)->Int;
sayClosure = {(x :Int,b: Int)->Int in return x + y }
sayClo(100,200)
/** OC中Block定义方式 定义上面的闭包函数
int (^sumBlock)(int,int);
sumBock = ^int(inta,int b){ return a + b; };
typedef double(^SumBlock)(int,int); 定义了一个SumBlock的类型
SumBlock s =^double(int i1,int i2) { return i1 + i2; };
*/
7 . Swift中的冒泡排序,实现原理 挨个取出数组前面的数,然后将该数与它后面所有的数进行比较,根据大小调换数值。
func paopaoSort(inout data[Int],function:(Int,Int)->Int) {
for var i =0;i < data.count - 1;i++ {
for var j = i+1; j< data.count; j ++ { // i+1 表示从 i后面的数开始逐个取出与i进行比较
if (function(data[i],data[j]))
swap(&data[i],&data[j]) }}}
let data:[Int] = [9,3,56,7,8]
func sortDes( a:Int, b:Int )-> Bool { return b - a }
func sortAsc( a, b) -> Bool { return a - b } //根据a,b传入值的类型可以省略 Int ,Int
paopaoSort(&data,function: sortDes)
paopaoSort(&data,function: sortAsc)
//其它奇葩的写法:
sortData(&data){$0 < $1} // $0表示第一个参数 , $1表示第二个参数; 再运行的时候判断
data[i] < data[j ]
sortData(&data,function: >) //把> 做为一个函数参数整体 ; 再调用的时候相当于讲function(data[i],data[j]) 替换成了 >
8. Swift中默认的函数相关用法
var names = ["aaa","ddd","fdsaf","fdsa"]
names.sort() //会自动对数组names中的元素进行排序
name.sort{ (a,b) -> Bool in return a > b} //也可以通过此方式返回a与b的比较结果决定排序顺序。当sort函数或得此Bool值后,内部根据降序活着升序自动进行排序运算。
names.sort{ return $0 > $1 } //具有相同的功效
var numbers:[Int] = [1,35,5643,653]
//map方法,把数组中的每个元素都取出来,放入闭包函数中执行,把所有执行的结果放入新的数组中
//下面这句话表示从通过numbers 中取出每个元素,然后进行相加,最后返回一个所有元素+20后的新的数组
var newNumber = numbers.map{ (number:Int) in return number + 20 }
也可以写成
var newNums2 = numbers.map({(x) -> Int in retunr x +10 })
当然还可以写成多种方法,自己慢慢摸索去,基本之遥不报错就Ok了
/**拖尾闭包(尾随闭包) 如果一个函数中最后的一个参数是闭包函数或闭包函数,可以将其写在()外面*/
如下定义的函数: 该函数中最后一个参数 function:(Int)->Int 闭包函数
func test(a:Int, b Int , function:(Int)->Int ) { }
test(100,b:200) {(x) -> Int in return x + 10 }
test(100,b:200, function:{(x)->Int in return x + 100})
4 .Swift函数|闭包的更多相关文章
- Swift函数|闭包
在编程中,我们常把能完成某一特定功能的一组代码,并且带有名字标记类型叫做函数,在C语言中,我们知道函数名就是一个指针,它指向了函数体内代码区的第一行代码的地址,在swift中也具有同样的功效. 在Sw ...
- Swift语法基础入门三(函数, 闭包)
Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...
- Swift: 比较Swift中闭包传值、OC中的Block传值
一.介绍 开发者对匿名函数应该很清楚,其实它就是一个没有名字的函数或者方法,给人直观的感觉就是只能看到参数和返回值.在iOS开发中中,它又有自己的称呼,在OC中叫Block代码块,在Swift中叫闭包 ...
- Swift:闭包
一.闭包的介绍 闭包表达式(Closure Expressions) 尾随闭包(Trailing Closures) 值捕获(Capturing Values) 闭包是引用类型(Closures Ar ...
- Swift函数编程之Map、Filter、Reduce
在Swift语言中使用Map.Filter.Reduce对Array.Dictionary等集合类型(collection type)进行操作可能对一部分人来说还不是那么的习惯.对于没有接触过函数式编 ...
- 如何在C语言中调用Swift函数
在Apple官方的<Using Swift with Cocoa and Objectgive-C>一书中详细地介绍了如何在Objective-C中使用Swift的类以及如何在Swift中 ...
- Swift学习--闭包的简单使用(三)
一.Swift中闭包的简单使用 override func viewDidLoad() { super.viewDidLoad() /** 闭包和OC中的Block非常相似 OC中的block类似于匿 ...
- iOS - Swift Closure 闭包
1.Closure 闭包在 Swift 中非常有用.通俗的解释就是一个 Int 类型里存储着一个整数,一个 String 类型包含着一串字符,同样,闭包是一个包含着函数的类型.有了闭包,你就可以处理很 ...
- Swift使用闭包表达式
Swift中的闭包表达式很灵活,其标准语法格式如下:{ (参数列表) ->返回值类型 in 语句组}其中,参数列表与函数中的参数列表形式一样,返回值类型类似于函数中的返回值类型,但不同的是 ...
随机推荐
- session生命周期
session生命周期 原文链接:http://blog.sina.com.cn/s/blog_72c8c1150100qpgl.html 文中黄色字体为我的标记修改或添加 Session保存在服务器 ...
- 滚动固定TAB在顶部显示
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- MVC4脚本压缩 BundleTable bundles 404错误
在发布网站的时候,因为使用了MVC4的新特性BundleTable,造成访问的时候js和css报了404错误, google了以后, 有朋友说是因为要在webservice添加 <modules ...
- 关于mac下面用Parallels装ubuntu时分辨率问题[已解决]
最近由于要深入下Android系统,在Parallels虚拟机上安装了ubuntu系统,刚开始安装成功的时候,分辨率只有800*600.本来想着去设置里面改动呢,可是坑爹的是设置里面只有800*600 ...
- [Virtualization][qemu][kvm][virtio] 使用 QEMU/KVM 模拟网卡多队列
序: 做DPDK例子的时候,发现一些例子需要多队列,而我当前所使用的虚拟机并不是多队列的.关于我当前虚拟机的状态,可以见前文. 所以,我的需求就是,让虚拟机里的网卡,有多队列! 参考: http:// ...
- youtube视频下载
开你的电脑,然后打开你的浏览器,浏览器可以是IE.Chrome.Firefox等等 在浏览器中输入这个网址:en.savefrom.net,点击Enter键,进入这个网页: 打开你需要下载的y ...
- Yii常用路径说明
原作者地址:http://www.kuitao8.com/20140520/2483.shtml //framework路径 Yii::getFrameworkPath(); //protected/ ...
- 浏览器同步测试神器 — BrowserSync
Browsersync 能让浏览器实时.快速响应文件更改(html.js.css.sass.less等)并自动刷新页面.更重要的是 Browsersync可以同时在PC.平板.手机等设备下进项调试,当 ...
- mybatis父子表批量插入
<!--父子表批量插入 --> <insert id="insertBatch" parameterType="com.niwopay.dto.beni ...
- Vue 双层嵌套
这种的需要双层嵌套. 代码: <table id="ict-table" class="ict-table ict-report-table blue-theme& ...