您的位置:首页 > 移动开发 > Swift

Swift函数和闭包

2016-04-03 13:02 381 查看
简介:本文主要讲:函数的定义,外部参数的用处,无返回类型的三种函数定义方式

闭包的定义,闭包的概念和用法,尾随闭包的写法,解除循环引用的方法

一、函数:

代码实现

函数的定义

格式
func 函数名(行参列表) -> 返回值 {代码实现}


调用
let result = 函数名(值1, 参数2: 值2...)


func sum(a: Int, b: Int) -> Int {
return a + b
}

let result = sum(10, b: 20)


没有返回值的函数,一共有三种写法

省略

()

Void

func demo(str: String) -> Void {
print(str)
}
func demo1(str: String) -> () {
print(str)
}
func demo2(str: String) {
print(str)
}

demo("hello")
demo1("hello world")
demo2("olleh")


外部参数

在形参名前再增加一个外部参数名,能够方便调用人员更好地理解函数的语义

格式:
func 函数名(外部参数名 形式参数名: 形式参数类型) -> 返回值类型 { // 代码实现 }


Swift 2.0 中,默认第一个参数名省略

func sum1(num1 a: Int, num2 b: Int) -> Int {
return a + b
}

sum1(num1: 10, num2: 20)


[/code]

二、闭包:

与 OC 中的 Block 类似,
闭包
主要用于异步操作执行完成后的代码回调,网络访问结果以参数的形式传递给调用方

闭包的定义

定义一个函数

//: 定义一个 sum 函数
func sum(num1 num1: Int, num2: Int) -> Int {
return num1 + num2
}
sum(num1: 10, num2: 30)

//: 在 Swift 中函数本身就可以当作参数被定义和传递
let mySum = sum
let result = mySum(num1: 20, num2: 30)


定义一个闭包

闭包 = { (行参) -> 返回值 in // 代码实现 }

in
用于区分函数定义和代码实现

//: 闭包 = { (行参) -> 返回值 in // 代码实现 }
let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in
return x + y
}
sumFunc(num1: 10, num2: 20)


最简单的闭包,如果没有参数/返回值,则
参数/返回值/in
统统都可以省略

{ 代码实现 }

let demoFunc = {
print("hello")
}


基本使用

GCD 异步

模拟在后台线程加载数据

func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
print("耗时操作 \(NSThread .currentThread())")
})
}


尾随闭包,如果闭包是最后一个参数,可以用以下写法

注意上下两段代码,
}
的位置

func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("耗时操作 \(NSThread .currentThread())")
}
}


闭包的简写,如果闭包中没有参数和返回值,可以省略

func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("耗时操作 \(NSThread .currentThread())")
}
}

自定义闭包参数,实现主线程回调

添加没有参数,没有返回值的闭包

override func viewDidLoad() {
super.viewDidLoad()

loadData {
print("完成回调")
}
}

// MARK: - 自定义闭包参数
func loadData(finished: ()->()) {

dispatch_async(dispatch_get_global_queue(0, 0)) {
print("耗时操作 \(NSThread.currentThread())")

dispatch_sync(dispatch_get_main_queue()) {
print("主线程回调 \(NSThread.currentThread())")

// 执行回调
finished()
}
}
}


添加回调参数

override func viewDidLoad() {
super.viewDidLoad()

loadData4 { (html) -> () in
print(html)
}
}

/// 加载数据
/// 完成回调 - 传入回调闭包,接收异步执行的结果
func loadData4(finished: (html: String) -> ()) {

dispatch_async(dispatch_get_global_queue(0, 0)) {
print("加载数据 \(NSThread.currentThread())")

dispatch_sync(dispatch_get_main_queue()) {
print("完成回调 \(NSThread.currentThread())")

finished(html: "<h1>hello world</h1>")
}
}
}


[/code]

循环引用

建立
NetworkTools
对象

class NetworkTools: NSObject {

/// 加载数据
///
/// - parameter finished: 完成回调
func loadData(finished: () -> ()) {
print("开始加载数据...")

// ...
finished()
}

deinit {
print("网络工具 88")
}
}


实例化
NetworkTools
并且加载数据

class ViewController: UIViewController {

var tools: NetworkTools?

override func viewDidLoad() {
super.viewDidLoad()

tools = NetworkTools()
tools?.loadData() {
print("come here \(self.view)")
}
}

/// 与 OC 中的 dealloc 类似,注意此函数没有()
deinit {
print("控制器 88")
}
}


运行不会形成循环引用,因为 loadData 执行完毕后,就会释放对 self 的引用



修改
NetworkTools
,定义回调闭包属性

/// 完成回调属性
var finishedCallBack: (()->())?

/// 加载数据
///
/// - parameter finished: 完成回调
func loadData(finished: () -> ()) {

self.finishedCallBack = finished

print("开始加载数据...")

// ...
working()
}

func working() {
finishedCallBack?()
}

deinit {
print("网络工具 88")
}


运行测试,会出现循环引用


解除循环引用

与 OC 类似的方法

/// 类似于 OC 的解除引用
func demo() {
weak var weakSelf = self
tools?.loadData() {
print("\(weakSelf?.view)")
}
}


Swift 推荐的方法

loadData { [weak self] in
print("\(self?.view)")
}


还可以

loadData { [unowned self] in
print("\(self.view)")
}

闭包(Block) 的循环引用小结

Swift

[weak self]


self
是可选项,如果self已经被释放,则为
nil


[unowned self]


self
不是可选项,如果self已经被释放,则出现
野指针访问


Objc

__weak typeof(self) weakSelf;


如果
self
已经被释放,则为
nil


__unsafe_unretained typeof(self) weakSelf;


如果
self
已经被释放,则出现野指针访问
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: