- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
注:本文为作者自己总结,过于基础的就不再赘述 ,都是亲自测试的结果。如有错误或者遗漏的地方,欢迎指正,一起学习。
swift中闭包是一个很强大的东西,闭包是自包含的函数代码块,可以在代码中被传递和使用。跟C 和 Objective-C 中的代码块(blocks)很相似 。这个大家必须掌握!必须掌握!必须掌握!重要的事情要说三遍
闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。下面我们就来攻克它!
官方在讲解闭包函数的时候一般都是使用一个sort()
的排序方法,我们来看看这个例子:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
这里我们定义了一个String
类型的数组,然后定义了一个function
,接受两个 接收两个String
类型的参数,返回bool
然后我们来了解下sort()
我们这里对这个数组进行排序 按照我们定义的方法的规则,var reversed = names.sort(backwards)
这个sort()
在swift 2.0加入数组,成为数组的成员方法可以直接调用 ,这里传入与数组类型相同的两个值 ,并返回bool
,如果返回true 就把第一个参数放在第二个前面 (也就是降序),反之你懂的
所以 ,我们这个函数的意思就是如果第一个比第二个参数大就返回true(s1>s2) ,所以是一个降序的排列 ,这里得到的结果是 :[Ewa, Daniella, Chris, Barry, Alex]
大家看着官方的sort()
也看不到具体的实现,所以这块有可能不是很清楚 ,那么我们自己写一个排序 ,也传入我们这个函数。
func mySort (var arr:[String] , sortStr:(String,String)->Bool)->[String]
{
if(arr.count == 0){ return arr; }
let count = arr.count
var temp = ""
for i in 0..<count
{
for j in i+1..<count
{
if(!sortStr(arr[i],arr[j]))
{
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
}
return arr;
}
者其实就是一个简单的冒泡排序 ,只不过把规则交给调用者 。
调用方法 mySort(names, sortStr: backwards)
这里传入的是一个数组和一个函数类型 。得到结果 :[Ewa, Daniella, Chris, Barry, Alex]
跟官方的sort一样的 。
下面的实例我们就用自己的sort 来讲,代码都在这里。大家可以看得明白 。
这里需要补充一个知识点。
区间运算 :0...n 表示0-n的闭合区间 0..<n 表示一个包含0 不包含n半开半闭
然而这是一个相当冗长的方式,本质上只是写了一个单表达式函数 (a > b),但是我们还要写一个函数 ? 当然不需要,下面我们用闭合表达式语法可以更好的构造一个内联排序闭包
闭包表达式语法有如下一般形式:
{ (parameters) -> returnType in
statements
}
闭包表达式语法可以使用常量、变量和inout类型作为参数,不提供默认值。 也可以在参数列表的最后使用可变参数。 元组也可以作为参数和返回值。
let arr1 = mySort( (names) , sortStr: { (s1:String,s2:String) -> Bool in
return s1>s2
})
这里我们把上面传入函数的地方,我们传入了一个闭包。这里就不做过多解释。完全按照上面的语法类型
因为我们写的mySort
第二个参数是类型为(String, String) -> Bool的函数,因此实际上String,String和Bool类型并不需要作为闭包表达式定义中的一部分。 因为所有的类型都可以被正确推断,返回箭头 (->) 和围绕在参数周围的括号也可以被省略:
所以我们的可以这样写 :
let arr2 = mySort( (names) , sortStr: { s1,s2 in return s1>s2 })
看到没,智能的swift帮我们把闭包缩短了很多
单行表达式闭包可以通过隐藏return关键字来隐式返回单行表达式的结果,我们这里是单行表达式 。注:不要方便的用惯了多行表达式别也给省略了
let arr3 = mySort( (names) , sortStr: { s1,s2 in s1>s2 })
我们的代码又短了很多
这时候我们的闭包就变成了下面这样
let arr4 = mySort( (names) , sortStr: { $0>$1 })
哇!太厉害了,swift太强大了,你以为这是终极目标了,错了 还有更厉害的
Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值
您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现
最终我们的闭包变成了这样
let arr5 = mySort( (names) , sortStr: > )
print(arr5) //[Ewa, Daniella, Chris, Barry, Alex]
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
let arr6 = mySort(names) { $0>$1 }
当闭包非常长以至于不能在一行中进行书写时,尾随闭包变得非常有用。这中方式也是我们经常时候的方式
闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
看到这段话是不是很晕呀,哈哈我们来看一个实例你就理解了 。
func makeRunStep(step:Int)->()->Int
{
var total = 0;
// func run()->Int {
// total+=step ;
// return total;
// }
return {()-> Int in total+=step ;
return total; }
}
这里我们定义了一个函数,传入一个Int
,返回()->Int
的函数类型 。在函数中我们定义一个统计总数的变量total
,直接返回一个闭包 ,在闭包中使用传入的参数和变量total
,我们这里也可以用我注释的那段,写一个内嵌函数 ,然后返回这个内嵌函数 。
let ten = makeRunStep(10);
这里传入一个10 ,并把返回的函数类型赋值给一个常量ten 。
执行该方法ten()
得到结果 10
当我们再去执行ten()
的时候,由于没有修改step,这里total实际上捕获并存储了该变量的一个副本,而该副本随着闭包一同被存储在ten这个变量中,因为每次调用该函数的时候都会修改total的值,闭包捕获了当前total变量的引用,而不是仅仅复制该变量的初始值。捕获一个引用保证了当makeRunStep结束时候并不会消失,也保证了当下一次执行闭包时,total可以继续增加
所以得到的结果是 :20
let ten = makeRunStep(10);
ten() //10
ten() //20
ten() //30
ten() //40
let ten2 = makeRunStep(10);
ten2() //10
如果重新调用makeRunStep(7)
则重新开始计数
let seven = makeRunStep(7);
seven() //7
seven() //14
seven() //21
seven() //28
大家看到这几组数据大概明白什么意思了吧, 其实真正的原因是闭包是一个引用类型的 ,let ten = makeRunStep(10);
我们这里虽然用一个常量接收了这个闭包,但是直接接受了它的引用,并不是闭包本身 。
let ten = makeRunStep(10);
ten() //10
ten() //20
ten() //30
ten() //40
let ten1 = ten
ten1() //50
print(ten1()) //60
两个不同的常量可以同时引用一个闭包 。
关于闭包大致就这么多。如有疑问可以相互交流学习 。希望共同进步!
学习iOS,有他就够了,小码哥视频,传智、黑马、各种swift书籍
有没有办法在 .swift 文件(编译成 .swift 模块)中声明函数,如下所示: 你好.swift func hello_world() { println("hello world")
我正在尝试使用 xmpp_messenger_ios 和 XMPPFramework 在 iOS 上执行 MUC 这是加入房间的代码。 func createOrJoinRoomOnXMPP()
我想在我的应用程序上创建一个 3D Touch 快捷方式,我已经完成了有关快捷方式本身的所有操作,它显示正确,带有文本和图标。 当我运行这个快捷方式时,我的应用程序崩溃了,因为 AppDelegate
我的代码如下: let assetTag = Expression("asset_tag") let query2 = mdm.select(mdm[assetTag],os, mac, lastRe
我的 swift 代码如下所示 Family.arrayTuple:[(String,String)]? = [] Family.arrayTupleStorage:String? Family.ar
这是我的 JSON,当我读取 ord 和 uniq 数据时出现错误 let response2 : [String: Any] = ["Response":["status":"SUCCESS","
我想将 swift 扩展文件移动到 swift 包中。但是,将文件移动到 swift 包后,我遇到了这种错误: "Type 'NSAttributedString' has no member 'ma
使用CocoaPods,我们可以设置以下配置: pod 'SourceModel', :configurations => ['Debug'] 有什么方法可以用 Swift Package Manag
我正在 Xcode 中开发一个 swift 项目。我将其称为主要项目。我大部分都在工作。我在日期选择器、日期范围和日期数学方面遇到了麻烦,因此我开始了另一个名为 StarEndDate 的项目,其中只
这是 ObjectiveC 代码: CCSprite *progress = [CCSprite spriteWithImageNamed:@"progress.png"]; mProgressBar
我正在创建一个命令行工具,在 Xcode 中使用 Swift。我想使用一个类似于 grunt 的配置文件确实如此,但我希望它是像 Swift 包管理器的 package.swift 文件那样的快速代码
我假设这意味着使用系统上安装的任何 swift 运行脚本:#!/usr/bin/swift 如何指定脚本适用的解释器版本? 最佳答案 Cato可用于此: #!/usr/bin/env cato 1.2
代码说完全没问题,没有错误,但是当我去运行模拟器的时候,会出现这样的字样: (Swift.LazyMapCollection (_base:[ ] 我正在尝试创建一个显示报价的报价应用。 这是导入
是否可以在运行 Swift(例如 Perfect、Vapor、Kitura 等)的服务器上使用 RealmSwift 并使用它来存储数据? (我正在考虑尝试将其作为另一种解决方案的替代方案,例如 no
我刚开始学习编程,正在尝试完成 Swift 编程书中的实验。 它要求““编写一个函数,通过比较两个 Rank 值的原始值来比较它们。” enum Rank: Int { case Ace = 1 ca
在您将此问题标记为重复之前,我检查了 this question 它对我不起作用。 如何修复这个错误: error: SWIFT_VERSION '5.0' is unsupported, suppo
从 Xcode 9.3 开始,我在我的模型中使用“Swift.ImplicitlyUnwrappedOptional.some”包裹了我的字符串变量 我不知道这是怎么发生的,但它毁了我的应用程序! 我
这个问题在这里已经有了答案: How to include .swift file from other .swift file in an immediate mode? (2 个答案) 关闭 6
我正在使用 Swift Package Manager 创建一个应用程序,我需要知道构建项目的配置,即 Debug 或 Release。我试图避免使用 .xcodeproj 文件。请有人让我知道这是否
有一个带有函数定义的文件bar.swift: func bar() { println("bar") } 以及一个以立即模式运行的脚本foo.swift: #!/usr/bin/xcrun s
我是一名优秀的程序员,十分优秀!