Swift学习(2函数闭包)
函数的定义
1.函数的基础写法
func 函数名(形参列表)->返回值类型
例: func sum(x:int ,y:int) -> int{
return x+y
}
print(sun(x:10,y:50))
2.外部参数的使用,就是在形参前加一个名字,外部参数不会影响函数内部细节,外部参数会让外部调用看起来更加的直观
例:func sum(num1 x:int ,num2 y:int )-> int{
return x+y
}
print(sum(num1:30,num2:40))
使用“_”可以替代不关心的展示方式,常见的还有for循环中”i”如果没有用到的情况向,可以用“_”代替
func sun(_ x:int ,_ y:int )-> int{
return x+y
}
print(sum(30,40))
3.默认值:通过给参数设置默认值,在调用的时候,可以任意组合参数,如果不指定就使用默认值。但是在OC中是不能实现的,需要定义多个函数
例 :func sum(x:int=1,y:int=2)-> int{
return x+y
}
print(sum())
print(sum(x:10,y:10))
print(sum(x:10))
…
4.无返回值的情况:主要用在闭包
例: func demo() {}
func demo1() ->() {}
func demo2() ->void {}
闭包
1.闭包的定义:类似于OC的block,但是比block应用更广泛
OC中block是匿名的函数
swift中函数是特殊的闭包
1.提前准备好的代码
2.在需要的时候执行
3.可以当做参数传递
例1:OC中是不能实现的函数赋值
func sum(x:int=1,y:int=2)-> int{
return x+y
}
let f = sum
print(f(x:20,y:40))
例2:简单的闭包
没有参数和返回值的函数b1 (此情况下可以省略参数和返回值,包括”in”)
let b1 = {
print(“hello word”)
}
执行闭包
b1()
例3:带参数的闭包
闭包中,参数,返回值,实现代码都是写在{}中
{形参列表->返回值 in 实现代码}
需要用 “in” 来分割定义和实现
let b2 = {
(x:int) ->() in
print(x)
}
b2(100)
例4:带参数和返回值的闭包
let b3 = {
(x:int) -> int in
return x+200
}
print(b3(1111))
2.swift中GCD的使用方法
1.GCD:将任务添加到队列,指定执行任务的函数
2.翻译:队列调度任务(block/闭包),以同步/异步 的方式来执行
例:func loadData() ->(){
DispatchQueue.global().async{
print(“耗时操作 \(Thread.current())”)
DispatchQueue.main.async(execute:{
print(“主线程更新 ui \(Thread.current())”)
})
}
}
3.在异步执行任务,获取结果,通过 block/闭包 回调。 闭包的应用场景和block完全一致
格式定义特点
1.参数 -> 返回值
2. loadData(completion: (result : [String]) ->()) -> () 中(completion: (result : [String]) ->()) 参数,后面是返回值。
3.completion: (result : [String]) ->() 中 (result : [String]) 是参数 后面是返回值
例:func loadData(completion: (result : [String]) ->() ) ->(){
DispatchQueue.global().async{
print(“耗时操作 \(Thread.current())”)
Thread.sleep(forTimeInterval:1.0)
let json = [“头条”,”八卦”,”天气”]
DispatchQueue.main.async(execute:{
print(“主线程更新 ui \(Thread.current())”)
//执行闭包
completion(result: json)
})
}
}
调用
loadData{
(result) in
print(“获取成功 \(result)”)
}
4.尾随闭包:如果函数的最后一个参数是闭包,函数参数可以提前结束,最后一个参数直接使用{}包装闭包的代码(3的例子)
原始的调用方法(按照函数本身编写的结果)
loadData(
completion:{(result)->() in
print(“获取成功 \(result)”)
}
)
嵌套的尾随闭包是(系统)不会自动提示尾随闭包,例如2中的例子。当然也可以手动删除多余的来再次写成尾随闭包的样式,方便阅读
func loadData() ->(){
DispatchQueue.global().async{
print(“耗时操作 \(Thread.current())”)
DispatchQueue.main.async{
print(“主线程更新 ui \(Thread.current())”)
}
}
}
5.在OC中可以用{} 来区分作用域。但是在swift中是不行的,swift中遇到{}可能会识别为闭包
6.swift中的循环应用:
1.使用OC的方式
weak var weakSelf = self
loadData{
print(weakSelf?.view)
}
细节1:要使用var修饰 不能使用let 。 因为weak可能在运行时被修改。weak指向的对象一旦被释放,会自动设置为nil ,所有不能为let
细节2:?(可选解包)通常用于单纯发送消息,没有计算 !(强行解包) 强行解包必须有值,如果没有会造成崩溃,通常用于计算
2.Swift推荐方法
loadData{
[weak self] in
print(self?.view)
}
[weak self] 表示闭包中所有的self都是若引用,注意解包
3.Swift的一个特殊方法(不建议使用)
loadData{
[unowned self] in
print(self?.view)
}
[unowned self] 表示闭包中所有的都是 assign的,不会强引用。但是对象释放指针地址不会变化,如果对象被释放,继续调用就会造成野指针的问题
7. [weak self ]是闭包整self的弱引用,如果self被释放,会自动设置为nil,与OC中的 __weak等效
[unowned self] 是闭包中的self 的assign的 ,如果self被释放,指针地址保持不变,会出现野指针的错误,与OC中的 __unsafe_unretained 等效
//demo下载地址:https://github.com/fushengit/Learn-Swift