设为首页 加入收藏

TOP

【Swift学习】Swift编程之旅---闭包(十一)(一)
2017-10-13 10:24:16 】 浏览:2843
Tags:Swift 学习 编程 之旅 --- 闭包 十一

  闭包是可以在代码中被传递和使用的自包含功能模块,它很像c和oc中的block,和.net中的lambdasbas表达式。

  闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 包裹着这些常量和变量的包俗称闭包。Swift会为您管理在捕获过程中涉及到的内存操作。下面是闭包的3中表现形式

  • 全局函数是一个有名字但不会捕获任何值的闭包
  • 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
  • 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的没有名字的闭包

  Swift的闭包表达式拥有简洁的风格,并鼓励在常见场景中以实现语法优化,主要优化如下: 

  •  利用上下文推断参数和返回值类型
  •  单表达式(single-expression)闭包可以省略 return 关键字
  •  参数名称简写
  •  Trailing 闭包语法
 
   闭包表达式
   嵌套函数是一种在较复杂函数中方便进行命名和定义自包含代码模块的方式。 当然,有时候撰写小巧的没有完整定义和命名的类函数结构也是很有用处的,尤其是在处理一些函数并需要将另外一些函数作为该函数的参数时。下面闭包表达式的例子通过使用几次迭代展示了 sort 函数定义和语法优化的方式
 
   sort方法
  
Swift 标准库提供了 sort 函数,会根据您提供的排序闭包将已知类型数组中的值进行排序。 一旦排序完成,函数会返回一个与原数组大小相同的新数组,该数组中包含已经正确排序的同类型元素。
下面的闭包表达式示例使用 sort 函数对一个 String类型的数组进行字母逆序排序,以下是初始数组值:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

 

排序函数有两个参数:
1. 已知类型值的数组。
2. 一个闭包,采用相同类型的数组的内容的两个参数,并返回一个布尔值来表示是否将第一个值在排序时放到第二个值的前面或是后面。如果第一个值应该出现第二个值之前,闭包需要返回true,否则返回false。
 
该例子对一个  String 类型的数组进行降序排序,因此排序闭包需为 (String, String) -> Bool 类型的函数。
func backwards(s1: String, _ s2: String) -> Bool { return s1 > s2 } var reversed = names.sort(backwards) // reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

 

如果第一个字符串 (s1) 大于第二个字符串 (s2),backwards 函数则返回 true,表示在新的数组中 s1 应该出现在 s2 前。 字符中的 "大于" 表示 "按照字母顺序后出现"。 这意味着字母 "B" 大于字母 "A", 字符串 "Tom" 大于字符串 "Tim"。 其将进行字母逆序排序,"Barry" 将会排在 "Alex" 之前,依次类推。
 
然而,这是一个相当冗长的方式,本质上只是写了一个单表达式函数 (a > b)。 在下面的例子中,利用闭合表达式语法可以更好的构造一个内联排序闭包。
 
 
  闭包表达式语法
闭包表达式语法可以使用常量、变量和 inout 类型作为参数,但不提供默认值。 也可以在参数列表的最后使用可变参数。元组也可以作为参数和返回值。
reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 }) 

 

需要注意的是内联闭包参数和返回值类型声明与 backwards 函数类型声明相同。 在这两种方式中,都写成了 (s1: String, s2: String) -> Bool类型。 然而在内联闭包表达式中,函数和返回值类型都写在大括号内,而不是大括号外。
 
闭包的函数体部分由关键字 in 引入。 该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。
 
因为这个闭包的函数体部分如此短以至于可以将其改写成一行代码
reversed = sort(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )

 这说明 sort 函数的整体调用保持不变,一对圆括号仍然包裹住了函数中整个参数集合。而其中一个参数现在变成了内联闭包 。

 
   根据上下文推断类型
  因为排序闭包是作为函数的参数进行传入的,Swift可以推断其参数和返回值的类型。 sort 期望第二个参数是类型为 (String, String) -> Bool 的函数,因此实际上 String, String 和 Bool 类型并不需要作为闭包表达式定义中的一部分。 因为所有的类型都可以被正确推断,返回箭头 (->) 和 围绕在参数周围的括号也可以被省略:
reversed = sort(names, { s1, s2 in return s1 > s2 } ) 

 

际上任何情况下,通过内联闭包表达式构造的闭包作为参数传递给函数时,都可以推断出闭包的参数和返回值类型,这意味着您几乎不需要利用完整格式构造任何内联闭包。
 
然而,你也可以使用明确的类型,如果你想它避免读者阅读可能存在的歧义,这样还是值得鼓励的。这个排序函数例子,闭包的目的是很明确的,即排序被替换,而且对读者来说可以安全的假设闭包可能会使用字符串值,因为它正协助一个字符串数组进行排序。
 
   单行表达式闭包可以省略 return
单行表达式闭包可以通过隐藏 return 关键字来隐式返回单行表达式的结果,如上版本的例子可以改写为:
reversed = sort(names, { s1, s2 in s1 > s2 } ) 

 

在这个例子中,sort 函数的第二个参数函数类型明确了闭包必须返回一个 Bool 类型值。 因为闭包函数体只包含了一个单一表达式 (s1 > s2),该表达式返回 Bool 类型值,因此这里没有歧义,return关键字可以省略。
 
  参数名简写
Swift 自动为内联函数提供了参数名称简写功能,您可以直接通过 $0,$1,$2等名字来引用的闭包的参数的值。
 
如果您在闭包表达式中使用参数名称简写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称简写的类型会通过函数类型进行推断。 in 关键字也同样可以被省略,因为此时闭包表达式
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【代码笔记】iOS-iCarouselDemo 下一篇objective-c IOS应用更新

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目