Swift 入门之简单语法(四)
函数
目标
- 掌握函数的定义
- 掌握外部参数的用处
- 掌握无返回类型的三种函数定义方式
代码实现
- 函数的定义
- 格式
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)
闭包
与 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>")
}
}
}
循环引用
- 建立
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已经被释放,则出现野指针访问
- 如果
Swift 入门之简单语法(四)的更多相关文章
- Swift 入门之简单语法(六)
KVC 字典转模型构造函数 /// `重写`构造函数 /// /// - parameter dict: 字典 /// /// - returns: Person 对象 init(dict: [Str ...
- Swift 入门之简单语法(二)
可选项判断 由于可选项的内容可能为 nil,而一旦为 nil 则不允许参与计算 因此使用中,经常需要判断可选项的内容是否为 nil 单个可选项判断 let url = NSURL(string: &q ...
- Swift 入门之简单语法(一)
定义 let 定义常量,一经赋值不允许再修改 var 定义变量,赋值之后仍然可以修改 //: # 常量 //: 定义常量并且直接设置数值 let x = 20 //: 常量数值一经设置,不能修改,以下 ...
- Swift 入门之简单语法(五)
面向对象 目标 构造函数 构造函数的基本概念 构造函数的执行顺序 KVC 在构造函数中的使用及原理 便利构造函数 析构函数 区分 重载 和 重写 懒加载 只读属性(计算型属性) 设置模型数据(didS ...
- Swift 入门之简单语法(三)
集合 数组 数组使用 [] 定义,这一点与 OC 相同 //: [Int] let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 遍历 for num in nu ...
- Swift入门教程:基本语法(四)
可选类型 可选类型的使用场合 当一个值可能存在,可能不存在的时候,就用可选类型 比如查找字符k在某个字符串中的位置 如果字符串是"jake",说明k的位置存在,是2 如果字符串是& ...
- Swift入门教程:基本语法大全
原文:Swift入门教程:基本语法大全 简介: ...
- Swift入门教程:基本语法(一)
简介: 什么是S ...
- swift入门-day01-基本语法
主要内容: 1.常量和变量 2.Optional 3.控制流 4.循环 5.字符串 6.集合 变量和常量 定义 let 定义常量,一经赋值不允许再修改 var 定义变量,赋值之后仍然可以修改 自动推导 ...
随机推荐
- Flex——弹性布局
今天在做项目时,要一个500*100的页面区域做三个橱窗,尼玛可是恶心死我了!光是计算左右内外边距,左右宽度,就废了一上午时间~~好吧,我承认我的数学老师挂得早! 正在苦逼的列公式,定位图片,浮动文字 ...
- C语言本身并不提供输入输出语句
C语言本身并不提供输入输出语句,输入和输出操作是由函数来实现的.在C标准函数库中提供了一些输入输出函数,例如,printf函数和scanf函数.在使用他们时,千万不要误认为他们是C语言提供的“输入输出 ...
- 转账示例(二):service层面实现(本例采用QueryRunner来执行sql语句,数据源为C3P0)
缺点:Service层面把Dao层面的开启事务操作完成了1.自行创建C3P0Uti,account数据库,导入Jar包 2.Dao层面 接口: package com.learning.dao; im ...
- 面试题 ARC
什么是ARC ?ARC主要解决什么问题? ARC:自动引用计数. 要点..当对象被创建时 retain count+1, 当对象被release时 retain count-1, 当retain co ...
- IT职场经纬 |阿里web前端面试考题,你能答出来几个?
有很多小伙伴们特别关心面试Web前端开发工程师时,面试官都会问哪些问题.今天小卓把收集来的"阿里Web前端开发面试题"整理贴出来分享给大家伙看看,赶紧收藏起来做准备吧~~ 一.CS ...
- CF #344 D. Messenger KMP/Z
题目链接:http://codeforces.com/problemset/problem/631/D 给定两个压缩形式的字符串,如a3b5a4k7这样的形式 问A在B中出现次数. 分类讨论,如果A是 ...
- JS自定义对象,正则表达式,JQuery中的一些知识点
一:自定义对象 1.基本概念:①对象:包含一系列无序属性和方法的集合.②键值对:对象中的数据是以键值对的形式存在的,以键取值.③属性:描述对象特征的一系列变量.[对象中的变量]④方法:描述对象行为的一 ...
- 关于Integer与int
integer a=new integer(1); integer b=new integer(1); int c=1; integer d=1; a==b false因为地址不同: a==c t ...
- [ext4]空间管理 - 查找块
在文件系统中,当需要执行写操作时,肯定是需要查找需要写入的块.那么如何查找块哪? 在Ext4系统中,有两个函数是可能执行查找操作的:ext4_getblk().ext4_get_block(). ...
- git 利用分支概念实现一个仓库管理两个项目
需求描述:开发了一个网站,上线之际,突然另一个客户说也想要个一样的网站,但网站的logo和内部展示图片需要替换一下,也就是说大部分的后台业务逻辑代码都是一致的,以后升级时功能也要保持一致:刚开始想反正 ...